Apex单元测试结构及示例

发表于:2018-11-20 11:36

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:程程哥    来源:简书

  单元测试
  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()方法来自己建立模拟的查询结果
  
    上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。

《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号