25

Salesforce passes in the HTTPRequest made by the logic your testing into the mock implementation to help with this type of requirement. So in the HttpCalloutMock.respond method implementation. You can call req.getBody() and condition the response based on that, here is an example... @IsTest private with sharing class MultiHttpMockTest { public class ...


25

The doInvoke method on the mock interface passes in the stub and request parameters. You can use these to condition to dispatch the mock logic to various other mock implementations, while only registering a single mock implementation. Test.setMock(WebServiceMock.class, new MockDispatcher()); public class MockDispatcher implements WebServiceMock { ...


21

You need to call Test.setMock(...) in your test class once you've implemented the required interfaces to prevent this particular error message. You shouldn't need to use Test.isRunningTest() to test your call outs (and doing so give you untestable code).


19

This need is covered in Testing Apex Callouts using HttpCalloutMock. Specifically, see the Testing multiple HTTP callouts section. Here's the example they use: public class MultiRequestMock implements HttpCalloutMock { Map<String, HttpCalloutMock> requests; public MultiRequestMock(Map<String, HttpCalloutMock> requests) { this....


18

Here is perhaps the simplest form of a mock that deals with multiple requests. It is declared as an inner class of the test class so the idea is that it handles all the cases that the outer test class handles. In the respond method you can look at the endpoint of the request or the body of the request and use if/else logic to return the appropriate fake ...


16

As part of the isolation of the test context, Salesforce does not allow your code to make REST or SOAP callouts during test execution. This includes all code that's executed in test context, even if it is executed indirectly by the code you're explicitly testing, and it includes callouts to Salesforce itself. To test code that makes callouts, you must ...


13

This should now be fixed, Summer '20 patch 7 is live on almost all Summer 20 sandbox pods as of this edit This was caused by an attempt to fix a different callout testing related bug in Summer '20 (specifically, this one: https://success.salesforce.com/issues_view?id=a1p3A000000ATF1QAO) that clearly didn't work as we had intended. That fix is being rolled ...


11

When you pass a Type to the Test.setMock method, you need to pass the interface being implemented, not the class that implements it. Joy Test.setMock(HttpCalloutMock.class, new ProjectCalloutServiceMock()); No Joy Test.setMock(ProjectCalloutServiceMock.class, new ProjectCalloutServiceMock());


10

Having recently gone through this exercise, I'm not certain that you're properly creating the communities portal user. From what you posted of the code above, you first need an owner for the account. // THIS FAILS - because we try to run as a user we create @isTest static void testCalloutWithRunAsCreatedUser() { Are you already using RunAs at this point? ...


8

A common cause of this sort of error is a variable (called "test" or "Test") hiding the static class method reference Test.setMock. But if you have posted the complete source code it would not be that. Saving this first: @isTest global class WebServiceMockImpl implements WebServiceMock { global void doInvoke( Object stub, Object ...


8

If the query in your insertFunction returns more than one Account then you wil be performing this sequence: Http request database update HttpRequest database update ... which as the error message reports is not allowed (because it would potentially leave an uncommitted transaction open for many seconds which is expensive for the platform). If you ...


8

See Testing HTTP Callouts by Implementing the HttpCalloutMock Interface (emphasis added): For the first argument, pass HttpCalloutMock.class, and for the second argument, pass a new instance of your interface implementation of HttpCalloutMock, as follows: Test.setMock(HttpCalloutMock.class, new YourHttpCalloutMockImpl()); After this point, if an HTTP ...


6

you may want to include test.isrunningtest in your actual callout class to check you are not going to run actual callout and only test mock. take a look on this thread Testing HttpCallout with HttpCalloutMock and UnitTest Created Data


6

I've found I've had to add something like this in my actual Class methods to switch my testMock if I'm running a test. public String getActivityFile() { if(test.isRunningTest) { Test.setMock(WebServiceMock.clas, new WebserviceNumber2Mock()); } return new WebserviceNumber2().getActivityFile(); } Update 2018-05-22 Extending this idea, it'...


6

Since you said in your comment that disabling workflows allows it to pass I am going to assume that some of those workflows are email alerts. This is a know issue which I first reported back in April and now has a know issue associated with it that is unresolved. Issue with Email Alerts and Test.setMock - Uncommitted Work Pending Known Issue: https://...


6

The entire point of unit tests has nothing to do with coverage, but everything to do with avoiding regression bugs. By simply skipping testing, you're actually putting yourself at risk that something will change later that will cause a fatal error, in production, potentially preventing any of your users from doing anything. For example, a developer might ...


5

Here is where Test.startTest() and Test.stopTest() come in to play. Structure your test to do all the data setup, then call startTest(). Execute your tested method and then call StopTest(). Among the many things this does, is force @future methods and callouts to fire. If you couple start/stopTest with mocked http callouts and you should be good to go.


5

This may be a known issue -- recently reported and contemporaneous with your OP


5

Ahh, new Salesforce features. That said, if you're mocking, you're not really testing any of that functionality, just how the response is handled. You're also not calling a real server, so the endpoint doesn't really matter. I'm never a fan of having to do hoops around limited Test functionality, but seems like we can make do in the interim. So for the ...


5

An HTTP callout is code that you write within Salesforce to (generally) call out to an external API over HTTP. REST and SOAP are types of APIs. So, you could make a callout to an external SOAP API or a REST API. Think of doing a callout as wanting to communicate with someone, the protocol (REST or SOAP) is the format of the communication, and HTTP is the ...


5

The same way you'd test any other code, by executing the method under test. For example: @AuraEnabled public static String TestController(String username, String password) { try { String name = username; String pass = password; if(name == 'test@test.test' && pass == 'pass') return 'true'; } catch (...


5

This test works just fine for me: @IsTest class Demo { class Mock implements HttpCalloutMock { Boolean hasResponded = false; public HttpResponse respond(HttpRequest request) { HttpResponse response = new HttpResponse(); response.setStatusCode(hasResponded ? 204 : 200); hasResponded = true; ...


5

Write test-method for each possible scenario. For example, you have the following conditions: if(A) { if(subA) { do A and subA; } else { do A and not SubA; } } else { do not A; } to cover all lines of this condition: @isTest static void test_do_A_and_subA(){ setup A and subA test data; invoke method to test; ...


5

Yes, implementing a mock should be considered necessary. If you do not care about the response, it is quite simple: @IsTest public class MyMock implements HttpMock { public HttpResponse respond(HttpRequest request) { return null; } } My advice, never use Test.isRunningTest() unless there is no other way to accomplish what you desire. At least in this ...


4

I know this is a 'hack' but you may be able to call your batchable class methods inside your testmethod without running in a Database.executeBatch(...); method call. I have done this for a customer who needed higher test coverage; their batch apex was simple and didn't require the batchable context to be set. TestCode:- MyBatchableClass mbc = new ...


4

If you separate the HTTP callout from the @future method, you can test them individually and get full coverage. make the @future method return void, use Test.startTest() and Test.stopTest() around its invocation in test (so it executes synchronously), use HttpCalloutMock (as you are) to cover the now-separate HTTP caller, Note that you won't receive an SMS ...


4

In order to test the callout you should implement a HttpCalloutMock (official doc) to emulate the remote service, then set it in your test class Test.setMock(HttpCalloutMock.class, new YourHttpCalloutMockImpl()); Regarding to read the XML response, I recommend you to use de Dom class (official doc) Sample of how to read the response: HttpResponse ...


4

I saw this technique from Andrew a little while back, and it has been a lifesaver for testing complex WebServices. One addition to his answer is that I set the response directly in the mock class e.g. if(request instanceof MyWebService.GetService_element) { MyWebService.GetServiceResponse_element testresponse_x = new MyWebService....


4

Looks like you have the right components in the test but in the wrong order? You're using the Test.setMock() after the Insert DN; (and that insert has the side-effect of making the callout). Read through http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_callouts_wsdl2apex_testing.htm carefully. It doesn't involve a trigger but principle is ...


4

As an alternative to Daniel's great answer, one thing that we do at my org is created a Settings class to handle the fetching of settings. Methods within this class always return an instance of the custom setting. Instead of referencing custom settings directly, we always call the Settings class in all code that uses settings, which then instantiates the ...


Only top voted, non community-wiki answers of a minimum length are eligible