Apex单元测试
单元测试类
Salesforce中为Apex语言提供了完整的单元测试流程,包括单元测试类、测试的运行和结果分析等。
单元测试类是一种特殊的Apex类,基本语法和普通的Apex类一样。
单元测试类的结构是:
@isTest
private class MyTestClass {
    @isTest
    static void myTest() {
        // Test
    }
}
可以看到,“@isTest”是一个关键的注解,带有它的类和方法会被系统认定为单元测试的类和方法。
对于单元测试的方法,可以用“testMethod”关键字代替“@isTest”注解,比如:
static testMethod void myTest() {
    // Test
}
单元测试的方法必须定义在单元测试类中。
单元测试类和方法的访问控制权限并不重要。无论是定义为public还是private,系统都可以进入其中并执行测试代码。
断言函数
系统中提供了一组断言函数来进行结果的比较。它们主要包括:
- System.assert(condition, msg):用于判断某条件是否为真,如果不为真则给出错误信息
 - System.assertEquals(expected, actual, msg):用于判断期望的值是否和实际的值相同,如果不同则给出错误信息
 - System.assertNotEquals(expected, actual, msg):用于判断期望的值是否和实际的值不同,如果相同则给出错误信息
 
单元测试示例
在Developer Console中,可以新建两个Apex类,一个作为正常的类,另一个作为单元测试类使用。
正常的类中写入如下代码,将美元转化为欧元,汇率取0.9:
public class CurrencyConverter {
    public static Decimal GetEuroFromDollar(Decimal dollar) {
        Decimal euro = dollar * 0.9;
        return euro;
    }
}
在单元测试类中写入如下代码,测试函数的执行情况:
@isTest
private class CurrencyConverterTest {
    @isTest
    static void testGetEuroFromDollar() {
        Decimal euro = CurrencyConverter.GetEuroFromDollar(100);
        System.assertEquals(90, euro);
    }
}
在Developer Console中,可以直接点击单元测试类窗口右上角的“Run Test”按钮,则类中的测试方法会被自动执行,在窗口下方的控制台中会显示结果。“Logs”标签中会显示执行测试的日志,“Tests”标签中会显示哪些测试函数被执行以及执行结果。
代码覆盖率
Salesforce非常注重代码的覆盖率。系统规定的最低代码覆盖率是75%,也就是说每一个类的单元测试的范围要包括被测试的类的至少75%的代码。
在Developer Console中,当执行完一个单元测试类的所有测试之后,打开被测试的类,在编辑区域的左上方会有“Code Coverage”按钮,点击即可看到代码覆盖率。在下方“Tests”部分的右侧是所有类的覆盖率一览。
单元测试中的数据
在单元测试中,有时候需要新建对象数据或修改对象数据。所有单元测试中的数据都是独立于实际数据库的。
在单元测试开始的时候,默认为数据库是空的,不能直接从中读取已经存在的数据,必须手动新建。
当单元测试结束时,所有往数据库中增加、修改的数据都会被清理掉。
注意:虽然单元测试的数据独立于实际数据库,但是在单元测试中的数据也会暂时被保存在数据库中。所以如果在单元测试中新建了某条记录,而此记录的某些字段违反了验证规则,或者某些数据必须唯一的字段和显存的某些记录相同,系统会报错,测试无法继续进行。
比如:系统中设置了验证规则:所有“Account”对象的名字值是唯一的,并且已经存在了一个叫“Test Account”的对象,那么在测试类中新建一个叫“Test Account”的对象,则系统会报错。
设置测试数据
如果一个单元测试类中包含若干测试函数,而这些函数会用相同的一组数据,则可以使用“testSetup”注解定义单元测试类的初始化函数。
在初始化函数中建立的测试数据可以供每一个单元测试函数使用,并且在测试函数中对于数据库的更改并不会带到其他测试函数中,所以每一个测试函数在运行时,数据库中的状态都和执行完初始化函数的状态一样。
示例代码:
@isTest
private class ExampleTestSetup {
    // 使用testSetup定义初始化函数
    @testSetup
    static void setup() {
        List<Account> testAccts = new List<Account>();
        for(Integer i=0;i<2;i++) {
            testAccts.add(new Account(Name = 'TestAcct'+i));
        }
        insert testAccts;
    }
    @isTest
    static void testMethod1() {
        // 在setup()函数中插入数据库的testAccts对象可以在这里直接使用,并且其他测试函数对数据的更改不会在此函数中产生作用
        Account acct = [SELECT Id FROM Account WHERE Name='TestAcct0' LIMIT 1];
        acct.Phone = '555-1212';
        update acct;
        // ...
    }
    @isTest
    static void testMethod2() {
        // 在setup()函数中插入数据库的testAccts对象可以在这里直接使用,并且其他测试函数对数据的更改不会在此函数中产生作用
        // ...
    }
}
单元测试的限制
单元测试类中,有若干限制:
- 系统无法发送邮件
 - 系统无法和外部的网络服务通讯,所以无法通过调用web service得到数据,但是可以自己建立模拟数据
 - 无法使用SOSL查询,但是可以使用Test.setFixedSearchResults()方法来自己建立模拟的查询结果
 
Apex单元测试的更多相关文章
- Apex 单元测试辅助函数简介
		
startTest和stopTest的使用 在Apex的Test类中,有startTest和stopTest两个函数.这两个函数经常配对使用. 每个单元测试函数都只能调用它们一次. startTest ...
 - Apex 中文件夹相关的单元测试
		
Salesforce 中的文件夹 在 Salesforce 中,我们可以建立各种文档.报表.仪表板.电子邮件模板等.它们都被保存在相应的文件夹中. Salesforce 的后端将这些文件夹保存为 Fo ...
 - 异步 Apex 类
		
异步Apex类 一个Apex类可以定义为异步类,用于异步执行. 异步类可以通过多种方式实现: Future注解 批处理 Queueable接口 Schedulable接口 Future注解 使用Fut ...
 - 用 FFLIB 实现 Apex 企业设计模式
		
Apex 企业设计模式将应用分为服务层.模型层.选择逻辑层.工作单元几个部分.FFLIB 是一个开源的 Apex 框架,可以帮助开发者快速建立相关的功能. FFLIB 的安装 FFLIB 可以直接部署 ...
 - 从网络服务生成Apex类
		
使用WSDL2Apex从网络服务生成Apex类 如果某个网络服务被定义在WSDL文件中,而Salesforce必须使用SOAP和网络服务进行通信,则这种情况在某些时候会为开发者带来很多麻烦.为了简化S ...
 - Apex API 请求
		
Salesforce与网络服务的通信 在Salesforce中可以利用Apex类与远程站点的网络服务进行通信.当远程网络服务支持REST方法时,开发者可以利用Apex代码进行数据的操作. 设置远程站点 ...
 - Intellij idea添加单元测试工具
		
1.idea 版本是14.0.0 ,默认带有Junit,但是不能自动生成单元测试,需要下载JunitGererator2.0插件 2.Settings -Plugins,下载 JunitGenerat ...
 - Python的单元测试(二)
		
title: Python的单元测试(二) date: 2015-03-04 19:08:20 categories: Python tags: [Python,单元测试] --- 在Python的单 ...
 - Python的单元测试(一)
		
title: Python的单元测试(一) author: 青南 date: 2015-02-27 22:50:47 categories: Python tags: [Python,单元测试] -- ...
 
随机推荐
- 【安全狗SRC】抗D设备哪家强?你来!大佬告诉你答案
			
上周,安全狗SRC联合SRC部落,携手推出了爆款话题:传统抗D设备 vs 新兴CDN抗D:抗D效果哪个好? 一经发布简直好评如潮,热评无数,四方雷动(?)原帖在此,错过的吃瓜表哥们可以再围观一下~ht ...
 - jsp页面跳转页面的几中方式(同步更新)
			
1. 通过<a>标签跳转网页a) 通过<a>标签直接跳转b) 通过<a>标签调用JavaScript函数,然后再进行跳转 2. 通过表单形式跳转网页a) 通过表单跳 ...
 - Android分享内容和接收分享内容小小实现
			
先来说说分享,毕竟没有分享何来接收分享可谈? 分享目前已实现的有两种方式:后台代码实现.ShareActionProvider实现,接着先说通过代码实现 Intent intent=new Inten ...
 - The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar报错
			
缺少jstl依赖解析xml文件,报错jaspException 添加依赖如下: <dependency> <groupId>jstl</grou ...
 - [视频]K8软件破解脱壳入门教程
			
[视频]K8软件破解脱壳入门教程 链接:https://pan.baidu.com/s/1aV9485MmtRedU6pzyr--Vw 提取码:vbak C:\Users\K8team\Desktop ...
 - 解决vue路由history模式刷新后404的问题
			
server { listen ;#默认端口是80,如果端口没被占用可以不用修改 server_name localhost; root E:/vue/my_project/dist;#vue项目的打 ...
 - android_安装包_NoClassDefFoundError
			
说说这个问题出现的地方吧: 能够成功的打包安装包,但是在安装包安装后,准备运行时出现了这个问题. 查看了这篇文章,讲得有理有据,并没有解决我的问题. 通过谷歌查找到这个stackoverflow,解决 ...
 - Android开发之漫漫长途 XIX——HTTP
			
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
 - 函数调用的区别:_cdecl以及_stdcall
			
一.概念1)_stdcall调用 _stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,由调用者完成压栈操作,被调函数自身在返回前清空堆栈. WIN32 Api都采用_ ...
 - Vue.js的复用组件开发流程
			
本文由蔡述雄发表 接下来我们会详细分析下如何完成由多个组件组成一个复用组件的开发流程. 下面先看看我们的需求 列表组件quiList.vue 本节我们主要要完成这样一个列表功能,每一行的列表是一个组件 ...