batch apex를 실행하는 예약 가능한 클래스를 테스트하면 일관성없는 결과가 나타납니다.

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;
        }
    }

} 

schedulable 클래스는 execute 메서드에서 batch apex 만 실행합니다.

어떤 이유로 testInterfaceScheduler는 어설 션을 실패하고 testInterfaceBatch는 어설 션을 통과합니다. 이유를 알 수 없습니다. 도움을 주시면 감사하겠습니다.

감사합니다!

답변

1 cropredy Aug 19 2020 at 18:13

그 이유는 다음에 testInterfaceScheduler두 개의 비동기 트랜잭션을 실행하려고하기 때문입니다.Test.stoptest()

  • 예약 가능
  • 배치 가능

Test.stopTest ()는 assert 문을 계속하기 전에 첫 번째 비동기 트랜잭션 만 실행합니다. 디버그 로그는 실행중인 배치 파일을 보여 주지만 실제로는 어설 션 후에 (테스트 컨텍스트에서) 발생합니다.

이제이 문제를 해결하는 방법은 적절한 단위 테스트를 수행하는 것입니다.

  • 일정을 테스트 할 때 생성자와 execute () 메서드를 테스트하기 만하면됩니다. 당신이 정말로 신경 쓰는 것은 execute ()가 일괄 처리를 시작했다는 것입니다. 그리고 배치 가능에 대한 AsyncApexJob이 있는지 간단히 확인할 수 있습니다. 일괄 처리가 시작되는지 테스트 할 필요가 없습니다.
  • 당신이 batchable을 테스트 할 때, 당신은이에 대한 모의 개체를 제공 start()찾으려면 다음을 확인 execute()하고 finish()당신이 원하는 일을

생성자 인수를 일괄 처리 가능에 전달하는 경우 다음을 수행하여 적절한 인수로 일괄 처리 가능이 호출되는지 확인할 수 있습니다.

@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

}

Schedulable execute()은 다음과 같습니다.

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

즉, 배치 가능에 전달할 일부 인수를 스케줄링 가능에 종속성 주입합니다. 즉, 스케쥴링에 대해 인수 없음 생성자와 "인수 포함"생성자가 있습니다.