Il test di una classe pianificabile che esegue l'apice batch fornisce risultati incoerenti

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 classe schedulable esegue semplicemente l'apice batch nel metodo di esecuzione.

Per qualche ragione testInterfaceScheduler FAILS asserzione, mentre testInterfaceBatch PASSA l'asserzione. Non riesco a capire perché, qualsiasi aiuto è apprezzato.

Grazie!

Risposte

1 cropredy Aug 19 2020 at 18:13

La ragione di ciò è che testInterfaceSchedulerstai tentando di eseguire due transazioni asincrone dopoTest.stoptest()

  • Il pianificabile
  • Il batchable

Test.stopTest () esegue solo la prima transazione asincrona prima di continuare con l'istruzione assert. Il tuo log di debug mostrerà il batchable in esecuzione ma in realtà accade (nel contesto del test) dopo l'asserzione.

Ora, un modo per risolvere questo problema è eseguire un test di unità appropriato

  • quando si prova un pianificabile; devi semplicemente testare il suo costruttore e il metodo execute (). Quello che ti interessa davvero è che execute () abbia avviato un batchable. E puoi semplicemente verificare che sia presente un AsyncApexJob per il batchable. Non è necessario testare l'avvio del batchable.
  • quando si prova un batchable, si forniscono oggetti fittizi start()da trovare, quindi si verifica execute()e si finish()fa ciò che si desidera

Se stai passando gli argomenti del costruttore al batchable, puoi verificare che il batchable sia chiamato con gli argomenti corretti facendo:

@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

}

dove Schedulable ha execute()questo aspetto

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

Cioè, la dipendenza inietta nello schedulable alcuni argomenti che vuoi passare al batchable. Ciò significa che avrai un costruttore senza argomenti e un costruttore "con argomenti" per il tuo schedulable