Как избежать STANDARD_PRICE_NOT_DEFINED при модульном тестировании OpportunityLineItem в Apex v24.0?
По-видимому, новая особенность релиза Apex в Salesforce.com Spring '12/v24.0 заключается в том, что модульные тесты больше не имеют доступа к "реальным" данным - таким образом (если я правильно понимаю изменения ) SOQL-запрос теперь будет извлекать только те объекты, которые были вставлены в течение unit test, и даже с некоторыми ограничениями.
Во всяком случае, это, кажется, бросает OpportunityLineItem, проверяя окно, потому что:
- Невозможно вставить OpportunityLineItem без PriceBookEntryId, НО
- Вы не можете вставить новую книгу ценников для продукта X, если у вас уже нет записи стандартной цены для продукта X, НО
- В тестовых данных нет стандартной книги цены, потому что таблица Pricebook2, как и все таблицы, фактически пуста в начале прогона unit-test, AND
- В Apex нет возможности создать стандартную книгу цены
Я действительно надеюсь, что у меня есть хотя бы один из этих четырех пунктов, но пока никаких изменений в моих существующих модульных тестах не показалось, что кто-то из них ошибается. Это, конечно, означает, что мои модульные тесты больше не работают. Это произошло буквально в одночасье - тесты прошли отлично в моей песочнице в пятницу, и теперь они терпят неудачу.
Мне что-то не хватает, или это ошибка в новой версии SFDC?
Ответы
Ответ 1
Во-первых, чтобы успокоить ум, нет никаких планов, чтобы осудить флаг seeAllData. Мы не собираемся вытаскивать коврик из-под тебя. Что касается создания стандартной ценовой книги в тесте apex, я не уверен. Есть, я уверен, несколько областей, где тестирование без существующих данных сегодня сложно на платформе, что является одной из причин появления флажка seeAllData. Мы попытаемся закрыть эти пробелы в следующих нескольких выпусках.
Ответ 2
В Summer 14 появилась новая функциональность, теперь вы можете использовать Test.getStandardPricebookId()
для получения стандартного идентификатора ценники, не устанавливая SeeAllData
на True
.
Ответ 3
Я просто столкнулся с этим, и хотя ваш пост старый, это первый результат в Google, поэтому я подумал, что поделюсь тем, что сделал.
Моя базовая архитектура - это тестовый класс, который вызывает класс утилиты как способ создания тестовых данных "на лету" (есть другие способы, это моя привычка).
Краткая версия:
- установить все данные в true
- убедитесь, что стандартная книга цены активна.
- добавить запись цены в стандартную книгу цены - флаг как активный
- добавьте запись в прайс-лист для вас, цена цены - флаг как активный
Класс тестирования:
@isTest (seeAllData=true)
public with sharing class RMA_SelectLineItemsControllerTest {
static testmethod void testBasicObjects() {
Pricebook2 standard = [Select Id, Name, IsActive From Pricebook2 where IsStandard = true LIMIT 1];
if (!standard.isActive) {
standard.isActive = true;
update standard;
}
Pricebook2 pb = RMA_TestUtilities.createPricebook();
Product2 prod = RMA_TestUtilities.createProduct();
PricebookEntry pbe = RMA_TestUtilities.createPricebookEntry(standard,pb,prod);
}
}
Метод утилиты выглядит так (только показывая, что вокруг нового PBE):
public static PricebookEntry createPricebookEntry (Pricebook2 standard, Pricebook2 newPricebook, Product2 prod) {
System.debug('***** starting one');
PricebookEntry one = new PricebookEntry();
one.pricebook2Id = standard.id;
one.product2id = prod.id;
one.unitprice = 1249.0;
one.isactive = true;
insert one;
System.debug('***** one complete, ret next');
PricebookEntry ret = new PricebookEntry();
ret.pricebook2Id = newPricebook.id;
ret.product2id = prod.id;
ret.unitprice = 1250.0;
ret.isactive = true;
insert ret;
return ret;
}
Ответ 4
Еще одна работа вокруг будет заключаться в том, чтобы ваш триггер был осведомлен о запуске в тесте с использованием Test.isRunningTest(), но я думаю, что это решение не подходит к лучшему методу, который, я считаю, является целым, чтобы сделать тесты изолированными от уже существующих данных.
Возможно, Salesforce может сделать поле Pricebook2.isStandard пригодным для записи, если код работает в контексте теста, или для записи стандартной стандартной книги цены должен быть присвоен тот же статус, что и "Пользователь и профиль"
Ответ 5
Please let me know if anyone has used Test.getStandardPricebookId() and able to insert opportunity line item in test class. I tried this method with below mentioned code but got an error ": STANDARD_PRICE_NOT_DEFINED, No standard price defined for this product: []".
Note: I have seeAllData=false
ID standardPBID = Test.getStandardPricebookId();
PriceBook2 pb = new PriceBook2();
pb.name = 'GEW Water CMS';
pb.isActive=true;
insert pb;
Product2 prod= new Product2();
prod.name='TestProd';
prod.productcode='4568';
prod.isActive=true;
insert prod;
PricebookEntry standardPrice = new PricebookEntry(Pricebook2Id = standardPBID, Product2Id = prod.Id, UnitPrice = 10000, IsActive = true, currencyISOCode='USD' );
PriceBookEntry pbe= new PricebookEntry(pricebook2id=pb.id, product2id=prod.id,unitprice=2000, isActive=true, currencyISOCode='EUR');
insert pbe;
OpportunityLineItem oli = new OpportunityLineItem(OpportunityId = OppList[0].Id, pricebookentryid=pbe.id, UnitPrice = 100, Quantity = 1);
insert oli;