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,单元测试] -- ...
随机推荐
- Java 中 & | ^ 运算符的简单使用
背景 今天碰到了代码中的按位与运算,复习一下,先列一个各个进制数据表. 顺便复习一下十进制转二进制的计算方式: 接下来解释下这三个运算符: & 按位与,都转为二进制的情况下,同为1则为1,否则 ...
- 《http权威指南》读书笔记2
概述 最近对http很感兴趣,于是开始看<http权威指南>.别人都说这本书有点老了,而且内容太多.我个人觉得这本书写的太好了,非常长知识,让你知道关于http的很多概念,不仅告诉你怎么做 ...
- itext实现合同尾部签章部分自动添加,定位签名
使用的pom <!-- pdf处理 start--> <dependency> <groupId>com.itextpdf</groupId> < ...
- mint-ui Infinite scroll 重复加载、加载无效的原因及解决方案
1.无限滚动的运用场景: 一般运用在列表展示,有分页.下拉加载更多的需求中. 2.代码分析 代码很简单,实现了列表分页,数据加载完之后显示数据状态 <template> <div c ...
- MyBatis源码解析【8】简单demo理解接口式编程
前言 这个分类比较连续,如果这里看不懂,或者第一次看,请回顾之前的博客 http://www.cnblogs.com/linkstar/category/1027239.html 上一次我们经过源码的 ...
- Docker 数据卷和数据卷容器
1.本节课主要讲解如何在Docker内部及容器之间管理数据.容器中管理数据主要有两种方式:数据卷(Data volumes)数据卷容器(Data volume containers) 2.数据卷:是一 ...
- Angularjs 通过asp.net web api认证登录
Angularjs 通过asp.net web api认证登录 Angularjs利用asp.net mvc提供的asp.net identity,membership实现居于数据库的用户名/密码的认 ...
- JVM(一)—— 内存管理
JVM 内存结构 Java 虚拟机的内存空间分为 5 个部分: 程序计数器 Java 虚拟机栈 本地方法栈 堆 方法区 程序计数器(PC) 为什么需要程序计数器 因为Java虚拟机的多线程是通过线程轮 ...
- APiCloud学习
端API调用 核心模块在 window.api 对象下,默认提供该模块,不需要单独引用. 扩展模块在相应的模块对象下(例如:文件系统模块在fs对象下),需要require引入(var fs = api ...
- 《SQL Server从入门到精通》
书名 <SQL Server从入门到精通> 图片 时间 2017-6月 学习 书还可以看完不痛不痒 光盘里面是c的视频有趣这是要我学c的节奏啊,可以写一些基础sql语句也是一门语言叫T-s ...