У меня есть похожие вопросы, и все они упоминают API перед любым DML.

похожий вопрос 1 и похожий вопрос 2

Тем не менее, я пытаюсь выполнить API в execute, но все еще получаю сообщение У вас есть незавершенная работа, ожидающая выполнения. Пожалуйста, зафиксируйте или откатитесь, прежде чем вызывать , но я не понимаю, почему я получаю это, в начале нет DML, кроме Database.QueryLocator, но на основе этого ответа я понял, что это все еще можно сделать.

Когда я запускаю это в песочнице (без тестового метода), пакет работает правильно.

Мой класс:

// Database.executeBatch(new BatchMinIT5009(), 50);
global class BatchMinIT5009 implements Database.Batchable<sObject>, Database.AllowsCallouts, Database.Stateful {
    global Integer recordsProcessed = 0;
    global Boolean isSandbox;

    global Database.QueryLocator start(Database.BatchableContext bc) {         
        return Database.getQueryLocator(
            'SELECT Id, Loan_Number__c FROM Opportunity WHERE (StageName = \'Loan Funded\')'
        );
    }

    global void execute(Database.BatchableContext bc, List<Opportunity> scope){

        Set<String> scope_JSON = new Set<String>();
        Set<String> oppLoanNumberSet = new Set<String>();
        Map<String, Opportunity> oppLoanNumberMap = new Map<String, Opportunity>();

        for (Opportunity o:scope) {
            recordsProcessed++;
            scope_JSON.add(o.Id);
            oppLoanNumberSet.add(o.Loan_Number__c);
            oppLoanNumberMap.put(o.Loan_Number__c, o);            
        }

        //MY CALL OUT
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        HttpResponse res = new HttpResponse();
        req.setTimeout(120000);
        req.setEndpoint('https://eng963ivpdn16.x.pipedream.net/');
        req.setMethod('GET');
        req.setHeader('Accept', 'application/json');
        res = http.send(req);
        String api_res_body = res.getBody();        
        System.debug('%%% api res \n' + api_res_body); 

    }

    global void finish(Database.BatchableContext bc){
        isSandbox = HelperClass.runningInASandbox();
        AsyncApexJob job = [SELECT Id, Status, NumberOfErrors, 
        JobItemsProcessed,
        TotalJobItems, CreatedBy.Email
        FROM AsyncApexJob
        WHERE Id = :bc.getJobId()];

        String emailBody              = JSON.serialize(job);
        String emailTo                = 'email@email.com';
        String emailSenderDisplayName = 'Saving loans schedules - Original (5009)';
        String emailSubject           = 'Something was wrong, is sandbox: ' + String.valueOf(isSandbox);
        String emailReplyTo           = 'email@email.com';
        if (job.NumberOfErrors > 0) {
            String emailResponse          = HelperClass.emailMethod(emailTo,emailBody,emailSenderDisplayName,emailSubject,emailReplyTo);
        }
    }    
}

Мой тестовый класс:

static testMethod void test_MinIT5009() {

    Map<String, String> responseHeaders = new Map<String, String>();
    responseHeaders.put('Content-Type', 'text/xml');
    Test.startTest();
        Test.setMock(HttpCalloutMock.class, new Test_HttpCalloutMock(200, 'OK', 'OK:^2020-03-04~200~275189|2020-04-04~200~275190|2020-05-04~200~275191',responseHeaders));
        Database.executeBatch(new BatchMinIT5009(), 50);
    Test.stopTest();
}
0
manza 7 Апр 2020 в 04:53

1 ответ

Как вы создаете данные тестовой возможности... в методе @testSetup?

Я наблюдал некоторые сбои в работе, вызванные определенными комбинациями модульных тестов + выноски + асинхронный Apex + Test.startTest()/Test.stopTest() + Test.setMock + электронные письма рабочего процесса или электронные письма Apex. Происходит что-то запутанное, когда поведение свертывания асинхронной работы в одну транзакцию модульного теста вызывает ложную ошибку «У вас есть незафиксированная работа в ожидании».

Я не уверен в реализации вашего HelperClass.emailMethod, но, возможно, это похоже на то, что происходит здесь.

Иногда, чтобы получить надлежащее покрытие для Batchable, мне просто нужно протестировать каждый из его отдельных методов в отдельности. Это может быть другой путь.

2
Charles T 7 Апр 2020 в 06:08
Да, мои данные создаются в @testSetup, даже если я не запускаю HelperClass.emailMethod, я все равно получаю ту же ошибку, единственный раз, когда я не получаю ошибку, это если я делаю API в методе запуска (перед возвратом) или в конструктор класса (в настоящее время отсутствует), но я сделал это для проверки, так как мне нужно, чтобы каждая запись была обработана при выполнении для выполнения API
 – 
manza
8 Апр 2020 в 01:44
1
Тот факт, что он даже терпит неудачу, если вы не запускаете emailMethod... вот это тупик. Может быть, включить максимально точный журнал отладки, записать его из запуска модульного теста и найти любые признаки чего-либо, что может считаться DML.
 – 
Charles T
8 Апр 2020 в 17:00
1
Также возможно ли, что создание данных @testSetup запускает какие-либо рабочие процессы/процессы, отправляющие оповещения по электронной почте? Это может быть фактором сбоя.
 – 
Charles T
8 Апр 2020 в 17:05