salesforce - ¿Cómo evito STANDARD_PRICE_NOT_DEFINED cuando se realiza la prueba unitaria de un OpportunityLineItem en Apex v24.0?
apex-code force.com (5)
Aparentemente, una nueva característica de la versión Spring ''12 / v24.0 de Apex en Salesforce.com es que las pruebas unitarias ya no tienen acceso a datos ''reales'', por lo tanto (si estoy entendiendo el cambio correctamente) una consulta SOQL ahora solo recupere objetos que se hayan insertado durante el curso de la prueba de unidad, e incluso eso está sujeto a algunas limitaciones.
En cualquier caso, esto parece arrojar OpportunityLineItem fuera de la ventana, porque:
- Es imposible insertar un OpportunityLineItem sin un PriceBookEntryId, PERO
- No puede insertar una nueva entrada en el libro de precios para el producto X a menos que ya tenga una entrada en el Libro de precios estándar para el producto X, PERO
- No hay un Libro de Precios Estándar en los datos de prueba porque la tabla Pricebook2, como todas las tablas, está efectivamente vacía al comienzo de la ejecución de la prueba de unidad, Y
- No hay manera de crear un Libro de Precios Estándar en Apex
Realmente espero haber equivocado al menos uno de esos cuatro puntos, pero hasta ahora ninguna variación en mis pruebas unitarias existentes ha demostrado que alguno de ellos esté equivocado. Lo que por supuesto significa que mis pruebas de unidad ya no funcionan. Esto sucedió literalmente de la noche a la mañana: las pruebas funcionaron bien en mi caja de arena el viernes, y ahora fallan.
¿Me estoy perdiendo algo o es un error en la nueva versión de SFDC?
En primer lugar, para tranquilizarlo, nunca hay planes para dejar de usar el indicador seeAllData. No vamos a sacar la alfombra de debajo de ti. En cuanto a la creación del libro de precios estándar en una prueba de ápice, no estoy seguro. Hay, estoy seguro, varias áreas donde las pruebas sin datos existentes son difíciles en la plataforma hoy en día, por lo que la bandera seeAllData está ahí. Intentaremos cerrar esas brechas en los próximos lanzamientos.
Me acabo de encontrar con esto, y aunque tu publicación es antigua, es el primer resultado en Google, así que pensé en compartir lo que hice.
Mi arquitectura básica es una clase de prueba que llama a una clase de utilidad como una forma de crear datos de prueba sobre la marcha (hay otras formas, este es mi hábito).
Version corta:
- establecer ver todos los datos a verdadero
- asegúrese de que el libro de precios estándar está activo
- agregar una entrada de libro de precios para el libro de precios estándar - marcar como activo
- añada una entrada de libro de precios para que pruebe el libro de precios - marcar como activo
Clase de prueba
@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);
}
}
El método de utilidad se parece a esto (solo muestra eso alrededor del nuevo 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;
}
Otra solución alternativa sería hacer que su activador sea consciente de que se está ejecutando en una prueba utilizando Test.isRunningTest (), pero creo que esta solución pierde el punto de la mejor práctica, que creo que es el punto de hacer pruebas aisladas de pre- los datos existentes.
Tal vez Salesforce podría hacer que el campo Pricebook2.isStandard pueda escribirse si el código se está ejecutando en el contexto de una prueba, o si el registro del Libro de precios estándar específico debería tener el mismo estado que el Usuario y el Perfil.
Se introdujo una nueva funcionalidad en Summer 14, ahora puede usar Test.getStandardPricebookId()
para obtener el ID de libro de compras estándar sin tener que configurar SeeAllData
en True
.
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;