Testar uma classe programável executando o apex do lote fornece resultados inconsistentes
@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;
}
}
}
A classe programável apenas executa o ápice do lote no método execute.
Por alguma razão, testInterfaceScheduler FALHA na asserção, enquanto testInterfaceBatch PASSA na asserção. Não consigo descobrir o porquê, qualquer ajuda é apreciada.
Obrigado!
Respostas
A razão para isso é que testInterfaceScheduler
você está tentando executar duas transações assíncronas apósTest.stoptest()
- O agendável
- O batchable
Test.stopTest () executa apenas a primeira transação assíncrona antes de continuar com a instrução assert. Seu log de depuração mostrará o batchable sendo executado, mas isso realmente acontece (no contexto de teste) após a declaração.
Agora, uma maneira de corrigir isso é fazer testes de unidade adequados
- quando você testa um planejável; você simplesmente precisa testar seu construtor e método execute (). O que realmente importa é que execute () inicie um batchable. E você pode simplesmente verificar se há um AsyncApexJob para o batchable. Você não tem que testar se o batchable começa.
- ao testar um batchable, você fornece objetos fictícios para o
start()
encontrar, em seguida, verifica oexecute()
efinish()
faz o que quiser
Se você estiver passando args do construtor para o batchable, poderá verificar se o batchable é chamado com os args adequados fazendo:
@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
}
onde o Schedulable se execute()
parece com isto
public void execute(SchedulableContext sc) {
InterfaceBatch batchable = new InterfaceBatch(this.args); // from Dependency-injected constructor args
Database.executeBatch(batchable);
}
Ou seja, você injeta dependência no escalonável alguns argumentos que deseja passar para o batchable. Isso significa que você terá um construtor sem args e um construtor "com args" para o seu escalonável