单元测试

  1. 测试类不记录到 APEX 的 6MB 限制
  2. 测试方法不发送邮件
  3. 测试方法无法调用外部服务
  4. 测试中执行SOSL返回空结果,可以用 Test.setFixedSearchResults() 或者 SeeAllData=true
  5. 测试类中的SQL操作会自动回滚,但是不能违反主键约束,否则会报错

文档地址

普通类测试

注意:默认情况下,测试类无法访问业务数据,如果存在这种情况,需要使用 SeeAllData=true

官网不建议打开 SeeAllData=true ,因为测试环境和生成环境的业务数据可能不同,会导致测试结果不同

可以在测试类中初始化业务数据,就可以查询到响应的数据了,见 testDoPost3

@RestResource(urlMapping='/account_rest_api/*')
global with sharing class AccountRestApi{

    @HttpPost
    global static String doPost(String Name) {
        List<Account> accList = [SELECT Id,Name FROM Account WHERE Name =: Name LIMIT 1];
        // 测试类需要打开 SeeAllData=true ,否则 accList.isEmpty() 永远为 true
        if (accList.isEmpty()) {
            return 'not exists';
        }
        return 'exists';
    }
}
@isTest
private class AccountRestTest {

    @isTest(SeeAllData=true)
    static void testDoPost1() {
        // 数据库存在该用户名
        String response = AccountRestApi.doPost('测试啦啦啦');
        System.assertEquals('exists', response);
    }

    @isTest(SeeAllData=true)
    static void testDoPost2() {
        // 数据库不存在该用户名
        String response = AccountRestApi.doPost('没有的');
        System.assertEquals('not exists', response);
    }

    @isTest
    static void testDoPost3() {

        Account acc = new Account(Name = '没有的');
        insert acc;

        // 一般准备数据写在 startTest 前,断言逻辑写在 stopTest 后
        Test.startTest();
        String response = AccountRestApi.doPost('没有的');
        Test.stopTest();

        System.assertEquals('exists', response);
    }
}

trigger测试

trigger TestObjectTrigger on TestObject__c (before insert) {
    for (TestObject__c tj : Trigger.new) {
        if (tj.Phone__c == null) {
            tj.Phone__c = '不存在';
        }
    }
}
对于触发器的单元测试,还是填入 SeeAllData=true 吧,会省事很多
@isTest(SeeAllData=true)
private class TestObjectTriggerTest {

    @isTest
    static void testBeforeInsert()
    {
        Test.startTest();
        TestObject__c tj = new TestObject__c(Name = '🐶');
        insert tj;
        Test.stopTest();
        TestObject__c tj1 = [SELECT Phone__c from TestObject__c WHERE Name = '🐶'];
        System.assertEquals('不存在', tj1.Phone__c);
    }
}

公用测试数据

如果多个测试用例中需要使用 mock 数据,可以提取到数据工厂中

@isTest
public class AccountDataFactory {
    public static List<Account> createAccount(Integer row) {
        List<Account> accList = new List<Account>();
        for (Integer i = 0; i < row; i++) {
            accList.add(new Account(Name = '狗蛋' + i));
        }
        insert accList;
        return accList;
    }
}
@isTest
private class AccountRestTest {
    @isTest
    static void testDoPost() {
        // 从 数据工厂中获取 mock 数据
        List<Account> accList = AccountDataFactory.createAccount(1);
        Account acc = accList.get(0);

        Test.startTest();
        String response = AccountRestApi.doPost('狗蛋0');
        Test.stopTest();

        System.assertEquals('exists', response);
    }
}

调用外部服务测试

测试类中不允许调用外部服务,需要 mock 数据来进行测试调用外部服务

public class CallOut {

    public HttpResponse post()
    {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setMethod('POST');
        request.setEndpoint('https://www.test.com/login');
        request.setHeader('Content-Type', 'application/json;charset=UTF-8');
        request.setBody('{"account":"admin","password":"123456"}');
        HttpResponse response = http.send(request);
        return response;
    }
}
@isTest
global class CallOutMock implements HttpCalloutMock {

    global HttpResponse respond(HttpRequest request)
    {
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{"code":"1000","message":"用户名或密码错误"}');
        response.setStatusCode(200);
        return response;
    }
}
@isTest
private class CallOutTest {
    @isTest
    static void testCallOutGet()
    {
        Test.setMock(HttpCalloutMock.class, new CallOutMock());

        CallOut co = new CallOut();
        HttpResponse response = co.post();
        String contentType = response.getHeader('Content-Type');
        System.assert( contentType == 'application/json');
        String body = response.getBody();
        System.debug(body);
        String expectedValue = '{"code":"1000","message":"用户名或密码错误"}';
        System.assertEquals(expectedValue, body);
        System.assertEquals(200, response.getStatusCode());
    }
}

results matching ""

    No results matching ""