Wednesday, March 8, 2023

What is test class in salesforce? How to test callouts using HttpCalloutMock Interfaces?

 Test class is a critical component of the development process. 

Why it is necessary to write test class in salesforce?

For the development of robust, error-free code, It is necessary to have some mechanism which ensures whether a particular piece of code is working properly or not and for that Apex supports the creation and execution of unit tests. Unit tests are class methods that verify whether a particular piece of code is working properly. Unit test methods take no arguments, commit no data to the database.

Now, let us take a look at the important annotations in test class.

Test methods are flagged with the @IsTest annotation in the method definition. Unit test methods must be defined in test classes, that is, classes annotated with @IsTest.

@IsTest

private class SampleTestClass {

   // Methods for testing

   @IsTest static void testMethod1() {

      // code here

   }

   @IsTest static void testMethod2() {

      // code here

   }

}

Earlier we also used to have testMethod keyword which was used to define apex test methods.

@isTest

public class SampleTestClass {

static testMethod void testmethod1() {

// code here

}

}

Note:

The testMethod keyword is now deprecated. Use the @IsTest annotation on classes and methods instead. The @IsTest annotation on methods is equivalent to the testMethod keyword.

When deploying apex to a production organization unit tests must cover at least 75% of your Apex code. While only 75% coverage is needed to deploy apex class to production we should not bound ourselves to cover 75% only instead make sure that every use case of your application is covered, including positive and negative cases, as well as bulk and single records.

Test classes best practices:

1) We should always considered doing testing with bulk records.

2) We Should test "test cases" for both positive and negative test scenario.

3) Avoid using (SeeAllData=true) in test class because it might happen that the test class pass in sandbox but fails in production if data is not present in production.

4) Avoid using hardcoded id's in  test class.

How to test callouts using HttpCalloutMock Interfaces?

By default test methods cannot be used to test Callouts, so tests that perform callouts fails. Instead, use mock callouts. 

Testing HTTP Callouts by Implementing the HttpCalloutMock Interfaces.

The class that implements the HttpCalloutMock interface can be either global or public.

You can annotate this class with @isTest since it will be used only in test context. In this way, you can exclude it from your organization’s code size limit of 6 MB.

Sample syntax:

global class TestHttpCalloutMockImpl implements HttpCalloutMock {

    global HTTPResponse respond(HTTPRequest req) {

        // Create a fake response.

        // Set response values.

        // return response.

    }

}

Now, let us understand with an example below,

Apex class doing callout:

public class SampleCalloutApexClass {

    public static HttpResponse getDataFromExternalSystem() {

        HttpRequest req = new HttpRequest();

        req.setEndpoint('https://SomeInstance.com/example/test');

        req.setMethod('GET');

        Http h = new Http();

        HttpResponse res = h.send(req);

        return res;

    }

}

Implementing the HttpCalloutMock Interfaces

@isTest

global class TestMockHttpResponseGeneratorImpl implements HttpCalloutMock {

    global HTTPResponse respond(HTTPRequest req) {

       // Creating a fake response

        HttpResponse res = new HttpResponse();

      // Setting response values

        res.setHeader('Content-Type', 'application/json');

        res.setBody('{"example":"test"}');

        res.setStatusCode(200);

      // return response.

        return res;

    }

}


Test Class:

@isTest

private class SampleCalloutApexClassTest{

     @isTest static void testCallout() {

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

        HttpResponse res = SampleCalloutApexClass.getDataFromExternalSystem();

        String contentType = res.getHeader('Content-Type');

        System.assert(contentType == 'application/json');

        String actualValue = res.getBody();

        String expectedValue = '{"example":"test"}';

        System.assertEquals(actualValue, expectedValue);

        System.assertEquals(200, res.getStatusCode());

    }

}

No comments:

Post a Comment