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,单元测试] -- ...
随机推荐
- 微信小程序如何调用API实现数据请求-wx.request()
前言 微信小程序不存在ajax,那么它是如何实现数据请求功能的呢?在微信中提供了API的调用wx.request(OBJECT),这个是很不错的.下面就讲一下如何请求数据,简单到不行. wx.requ ...
- [CocoaPods]故障排除
安装CocoaPods 如果您在macOS 10.9.0-10.9.2上安装,当RubyGems尝试安装jsongem 时可能会遇到问题.要解决此问题,请遵循以下说明 从macOS 10.8升级到10 ...
- Swift5 语言指南(五) 基本运算符
一个运营商是一个特殊的符号,或者你使用来检查,更改或合并值的短语.例如,加法运算符(+)添加两个数字,如,和逻辑AND运算符()组合两个布尔值,如.let i = 1 + 2&&if ...
- 我来谈谈PHP和JAVA在web开发上的的区别
这里的标题写的是谈谈PHP和JAVA的区别,其实是委婉的说法,其实别人是想听PHP好还是JAVA好!!! 从而从中找到存在感!!! 因为由于我是从多年的php开发转到java开发的.所以最,不时的有好 ...
- Python模块——logging模块
logging模块简介 logging模块定义的函数和类为应用程序和库的开发实现了一个灵活的事件日志系统.logging模块是Python的一个标准库模块, 由标准库模块提供日志记录API的关键好处是 ...
- Comparable接口和Comparator接口的不同用法
两者都可用来在定义比较方法,然后用在排序中. Comparable是类本身继承的接口 Comparator实在类外定义一个排序的类 比较而言,觉得Comparator更灵活一些,但是Comparabl ...
- servlet 请求乱码解决
- kubernetes构建时容器的时间与宿主机不一致的解决方法
kubernetes默认使用docker容器部署的应用,会出现时间与主机不一致的情况 容器时间与主机差8个小时:主机的与容器的/etc/localtime不一致 解决方法:挂载主机的/etc/loca ...
- [USACO13DEC] Optimal Milking
Description n个点排成一排,点有点权,要求支持两种操作: 修改某个点的点权 询问取出任意多且不相邻的点的点权和最大值 Solution 跟最大子段和一样,可以用分治做,用线段树记录一下左右 ...
- python的类变量与实例变量以及__dict__属性
关于Python的实例变量与类变量,先来看一段可能颠覆世界观的例子 #!/usr/bin/env python # -*- coding: utf_8 -*- # Date: 2016年10月10日 ...