0

I'm trying to do a test in my test class for a httpcallout. below is the test class that I have written. I created a mochHttpResponseGeneratorCustom class. I'm setting that class to mock in my test method

Test.setMock(HttpCalloutMock.class, new MockHttpResponseGeneratorCustom());

I'm not inserting any records in my test method but I'm getting the following error.

System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out

Please look at the code and let me know if am missing anything.

@isTest
global class MockHttpResponseGeneratorCustom implements HttpCalloutMock {
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest req) {
        // Optionally, only send a mock response for a specific endpoint
        // and method.
        System.assertEquals('http://api.salesforce.com/foo/bar', req.getEndpoint());
        System.assertEquals('GET', req.getMethod());

        // Create a fake response
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        res.setBody('{"foo":"bar"}');
        res.setStatusCode(200);
        return res;
    }
}






static testmethod void testCallout() {
        // Set mock callout class 
        String startDate = string.ValueOf(system.today()-30);
        String endDate = string.ValueOf(system.today()-30);
        String hoursConv = '10';
        String minsConv = '200';

        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGeneratorCustom());

        // Call method to test.
        // This causes a fake response to be sent
        // from the class that implements HttpCalloutMock. 
        String res = myApexClass.myMethod(abclaim.Id,startDate,endDate,hoursConv,minsConv);


    }
  • 1
    No test.startTest();? – Girbot Apr 6 '17 at 13:39
  • 1
    It's a good pattern to always use Test.startTest() and Test.stopTest(), especially with asynchronous methods - Test.stopTest() guarantees that your asynchronous request will be executed. And test.startTest() resets governor limits. Try to wrap your String res = myApexClass.myMethod(abclaim.Id,startDate,endDate,hoursConv,minsConv); in Test.startTest() - Test.stopTest() – EvAzi Apr 6 '17 at 13:45
2

In the documentation for Testing Callouts it does not specifically state that the Test.setMock needs to be wrapped in test.starttest. In fact the example they give does not include it. But wrapping the code in start and stop test typically resolves the issue so give that a try first

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restful_http_testing_httpcalloutmock.htm

The purpose of test.startTest is to reset the transaction and commit the DML previously performed.

If wrapping in test.startTest and test.stopTest does not work then - I do not see any DML in your code (maybe it is not complete?). You will need to check your

myApexClass.myMethod

code for any DML prior to the callout. If any exists then the test is correctly failing because you cannot do that.

If you need more help, please post up the code from myApexClass.myMethod

As an aside, do not add asserts to your Mock class as you are severely limiting the usability of the class to a single purpose. Instead take a look at the code here for a framework to have a general mock class.

Help on Invokable Apex Test class and @Future callout Apex test Class

Code Below is ALL by sfdcfox

@isTest class MakeCalloutTest {
    // Simple echo callout class
    // Returns whatever response we tell it to when asked
    class EchoHttpMock implements HttpCalloutMock {
        HttpResponse res;
        EchoMock(HttpResponse r) {
            res = r;
        }
        // This is the HttpCalloutMock interface method
        public HttpResponse respond(HttpRequest req) {
            return res;
        }
    }

    @isTest static void test() {
        // Avoid using live data
        List<Lead> leads = new List<Lead>{ new Lead(LastName='Test',Company='test') };
        insert leads;
        // We tell it what to simulate
        HttpResponse res = new HttpResponse();
        res.setBody('<?xml version="1.0" encoding="utf-8"?><root U_Id="12345"></root>');
        res.setStatusCode(200);
        // This allows the callout to succeed
        Test.setMock(HttpCalloutMock.class, new EchoHttpMock(res));
        // Start the test
        Test.startTest();
        // Enqueue the future call
        MakeCallout.invokeleadcallout(leads);
        // Trigger future method
        Test.stopTest();
        // Verify logic
        leads = [select id__c from lead];
        System.assertEquals('12345', leads[0].Id__c);
    }
}

You create the response you want within the test class that will be using it. Makes the class useful to any test method that may be calling it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.