Probar una clase programable que ejecuta el ápice por lotes da resultados inconsistentes

Aug 19 2020
@isTest(seeAllData = false)
private class interfacetest {

    public static testMethod void testInterfaceScheduler(){
        Product2 testproduct = new Product2(Name='test product',ProductCode = '112233');
        insert testproduct;
        Test.startTest();
        InterfaceCalloutMock fakeResponse = new InterfaceCalloutMock(200);
        Test.setMock(HttpCalloutMock.class, fakeResponse);
        InterfaceSchedule InterfaceSc = new InterfaceSchedule();
        String sch = '0 0 23 * * ?';
        system.schedule('Test Interface Scheduler', sch, InterfaceSc);
        Test.stopTest();
        List<Product_Image__c> images = [select Id from Product_Image__c where Product__c =:testproduct.Id];
        system.assertEquals(1, images.size());
    }

    public static testMethod void testInterfaceBatch(){
        Product2 testproduct = new Product2(Name='test product',ProductCode = '112233');
        insert testproduct;
        Test.startTest();
        InterfaceCalloutMock fakeResponse = new InterfaceCalloutMock(200);
        Test.setMock(HttpCalloutMock.class, fakeResponse);
        InterfaceBatch Batchtest = new InterfaceBatch();
        database.executebatch(Batchtest,100);
        Test.stopTest();
        List<Product_Image__c> images = [select Id from Product_Image__c where Product__c =:testproduct.Id];
        system.assertEquals(1, images.size());
    }

    public class InterfaceCalloutMock implements HttpCalloutMock {
        Integer responseCode {get;set;}
        InterfaceCalloutMock(Integer responseCode){
            this.responseCode = responseCode;
        }
        public HTTPResponse respond(HTTPRequest req) {
            HttpResponse resp = new HttpResponse();
            resp.setStatusCode(responseCode);
            resp.setBody('[{"id":"31A3FCE7-DDEF-40D1-8365A8CAA8809348"}]');
            return resp;
        }
    }

} 

La clase programable simplemente ejecuta el vértice del lote en el método de ejecución.

Por alguna razón testInterfaceScheduler FALLA la aserción, mientras que testInterfaceBatch PASA la aserción. No puedo entender por qué, se agradece cualquier ayuda.

¡Gracias!

Respuestas

1 cropredy Aug 19 2020 at 18:13

La razón de esto es que testInterfaceSchedulerestá intentando ejecutar dos transacciones asincrónicas despuésTest.stoptest()

  • El programable
  • El batible

Test.stopTest () solo ejecuta la primera transacción asíncrona antes de continuar con la declaración de aserción. Su registro de depuración mostrará la ejecución por lotes, pero en realidad sucede (en el contexto de la prueba) después de la aserción.

Ahora, una forma de solucionar esto es hacer las pruebas unitarias adecuadas

  • cuando prueba un programable; simplemente necesita probar su constructor y el método execute (). Lo que realmente le importa es que execute () inició un archivo por lotes. Y simplemente puede verificar que haya un AsyncApexJob para el archivo por lotes. No tiene que probar que se inicia el proceso por lotes.
  • cuando prueba un lote, proporciona objetos simulados para que los start()encuentre, luego verifique execute()y finish()haga lo que quiera

Si está pasando argumentos de constructor al proceso por lotes, puede verificar que se llame al proceso por lotes con los argumentos adecuados haciendo lo siguiente:

@IsTest static void testBatchable() {
   InterfaceSchedule schedulable = new InterfaceSchedulable(args);
   Test.startTest();
   schedulable.execute(null);  // SchedulableContext can't be constructed
   Test.stoptest();  // batchable will execute now
   // do asserts

}

donde el Programable se execute()ve así

public void execute(SchedulableContext sc) {
  InterfaceBatch batchable = new InterfaceBatch(this.args);  // from Dependency-injected constructor args  
  Database.executeBatch(batchable);
}    

Es decir, su dependencia inyecta en el programable algunos argumentos que desea pasar al programable. Esto significa que tendrá un constructor no args y un constructor "con args" para su programable