Salesforce单元测试的问题
Salesforce的单元测试是强制的,不达到一定的代码覆盖率,就不能成功部署。但有时单元测试会造成麻烦。
最近碰到一个问题,写个batch apex job。取数据的soql大致是SELECT Id, Name, Status FROM CampaignMember WHERE Status IN ('foo', 'bar')。然后根据不同的Status进行不同的操作:
global void execute(Database.BatchableContext bc, List<CampaignMember> records) { for (CampaignMember r : records) { if (r.Status == 'FOO') { //do something } else if (r.Status == 'BAR') { //do something }
}
用真实数据(Salesforce里已有的数据)测试通过。
但是在写单元测试时出现了问题。因为一般来说,单元测试用的数据要自己插入,即
@IsTest public with sharing class someTest { @IsTest public static void testFoo() { CampaignMember cm = new CampaignMember(Status = 'foo'); insert cm; } }
但测试通不过,调试发现,原来是有个触发器把Status自动改成'something'。问题是那个触发器是managed package创建的,看不到代码,不清楚它的逻辑,也不知道是谁装的。
最后只能利用CampaignMember对象里一个可写的字段,做了个hack。先把测试代码改写成
@IsTest public with sharing class someTest { @IsTest public static void testFoo() { CampaignMember cm1 = new CampaignMember (Status = 'foo', SomeWriteableField = 'unitTestFoo'); insert cm1; CampaignMember cm2 = new CampaignMember (Status = 'bar', SomeWriteableField = 'unitTestBar');
insert cm2; String query = 'SELECT Id, Name, Status, SomeWriteableField FROM CampaignMember WHERE Id IN (\'' + cm1.Id + ',\'' + cm2.Id + '\')'; Test.startTest(); Database.executeBatch(new SomeBatchable(query), 2); Test.stopTest(); System.assert(......) } }
然后改写原来的处理代码:
global class SomeBatchable implements Database.Batchable<SObject>, Schedulable { global String query; global SomeBatchable() { query = 'SELECT Id, Name, Status, SomeWriteableField FROM CampaignMember WHERE Status IN (\'FOO\', \'BAR\')'; } global SomeBatchable(String q) { query = q; } global Database.QueryLocator start(Database.BatchableContext bc) { return Database.getQueryLocator(query); } global void execute(Database.BatchableContext bc, List<CampaignMember> records) { for (CampaignMember r : records) { String unitTestType = ''; try { if (r.SomeWriteableField == 'unitTestFoo') { unitTestType = 'foo'; } else if (r.SomeWriteableField == 'unitTestBar') { unitTestType = 'bar'; } } catch (Exception e) {//若没有取SomeWriteableField字段,会抛异常,但不用管
} if (r.Status == 'FOO' || unitTestType == 'foo') { //do something
} else if (r.Status == 'BAR' || unitTestType == 'bar') { //do something
}
}
}
}
通过这样肮脏的hack代码,总算通过了单元测试。本来单元测试是为了保证程序没有错,但现在反而要修改程序来迁就单元测试,由此可见单元测试的垃圾的一面。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律