Salesforce Apex,测试类:
我正在尝试创建一个 TestClass 并在 apex 中为批处理脚本实现 100% 的代码覆盖率。我正在测试的类如下所示:
public class UpdateContractStatusBatch implements Database.Batchable<sObject>, Schedulable {
public Database.QueryLocator start(Database.BatchableContext BC) {
String query = 'SELECT Id, Status__c, SBQQ__RenewalForecast__c FROM Contract WHERE Status__c = \'Activated\' AND Legacy_Contract__c = false';
return Database.getQueryLocator(query);
}
public void execute(Database.BatchableContext BC, List<Contract> scope) {
if (scope.size()==0){
return;
}
List<Contract> contractsToUpdate = new List<Contract>();
List<Database.SaveResult> results;
try {
for(Contract con : scope) {
con.Status__c = 'Renewal Forecasted';
con.SBQQ__RenewalForecast__c = true;
contractsToUpdate.add(con);
}
results = Database.update(contractsToUpdate, false);
} catch (Exception e) {
System.debug('Exception in batch execute: ' + e.getMessage());
}
for (Database.SaveResult sr : results) {
if(!sr.isSuccess()) {
for(Database.Error err : sr.getErrors()) {
System.debug('Error updating contract Id: ' + sr.getId() + ' - ' + err.getMessage());
}
}
}
}
for (Database.SaveResult sr : results) {
if(!sr.isSuccess()) {
for(Database.Error err : sr.getErrors()) {
System.debug('Error updating contact ID: ' + sr.getId() + ' - ' + err.getMessage());
}
}
}
}
public void finish(Database.BatchableContext BC) {
}
public void execute(SchedulableContext sc) {
Database.execueBatch(new UpdateContractStatusBatch());
}
}
这是我迄今为止实现 76% 代码覆盖率的测试类:
@isTest
private class UpdateContractsStatusBatchTest{
@isTest
static void testBatch(){
// Create admin user
Profile adminProfile = [SELECT Id FROM Profile WHERE Name = 'System Administrator' LIMIT 1];
User adminUser = new User(
Alias = 'admin',
Email = '[email protected]',
EmailEncodingKey = 'UTF-8',
LastName = 'Admin',
LanguageLocalKey = 'en_US',
LocaleSidKey = 'en_US',
ProfileId = adminProfile.Id,
TimeZoneSidKey = 'America/Los_Angeles',
UserName = '[email protected]',
ByPassValidation__c = true
);
insert adminUser;
// Run the test as athe admin user
System.runAs(adminUser) {
// create product
Product2 sp = new Product2(
Name = 'Test Subscription',
IsActive = true,
SBQQ__PricingMethod__c = 'List',
SBQQ__SubscriptionPricing__c = 'Fixed Price',
SBQQ__SubscriptionTerm__c = 12,
Status__c = 'Draft'
);
insert sp;
Id pbid = Test.getStandardPriceBookId();
PricebookEntry spbe = new PricebookEntry(Product2Id = sp.id, Pricebook2Id = pbid, UnitPrice = 1, IsActive = true);
insert spbe;
// Create Account
Account a = new Account(Name = 'Test Account', BillingCity = 'St Albans');
insert a;
//Create Opps
Opportunity o = new Opportunity(
AccountId = a.Id,
Name = 'Test Opps',
StageName = 'Qualification',
CloseDate = Date.today(),
Pricebook2Id = pbid,
CurrencyIsoCode = 'USD',
Deal_Type__c = 'Direct',
Direct_Customer_Sales_Channel__c = 'Direct'
);
insert o;
// Create Quote
SBQQ__Quote___c q = new SBQQ__Quote___c(
SBQQ__Account__c = a.Id,
SBQQ__Opportunity2__c = o.Id,
SBQQ__Type__c = 'Quote',
SBQQ__Primary__c = true,
SBQQ__Pricebook__c = pbid,
SBQQ__StartDate__c = Date.today(),
SBQQ__EndDate__c = Date.today() + 365,
Deal_Type__c = 'Direct',
Sales_Channel__c = 'Direct',
SBQQ__SubscriptionTerm__c = 12,
SBQQ__Renewal__c = 8
);
insert q;
// Create Quote Line
SBQQ__QuoteLine__c sql = new SBQQ__QuoteLine__c (
SBQQ__Quote__c = q.Id,
SBQQ__Product__c = sp.Id,
SBQQ__Quanity__c = 1,
SBQQ__SubscriptionPricing__c = 'Fixed Price',
SBQQ__ProductSubscriptionType__c = 'Renewable',
SBQQ__SubscriptionType__c = 'Renewable',
SBQQ__DefaultSubscriptionTerm__c = 12,
SBQQ__SubscriptionTerm__c = 12,
SBQQ__StartDate__c = Date.today()
);
insert sql;
// Create Legacy_Contract__c = true
Contract c1 = new Contract(
AccountId = a.Id,
SBQQ__Opportunity__c = o.Id,
SBQQ__Quote__c = q.Id,
Status__c = 'Draft',
StartDate__c = Date.today(),
ContractTerm = 12,
Legacy_Contract__c = true,
SBQQ__PreserveBundlesStructureUponRenewals__c = true
);
insert c1;
// Create Legacy_Contract__c = false
Contract c2 = new Contract(
AccountId = a.Id,
SBQQ__Opportunity__c = o.Id,
SBQQ__Quote__c = q.Id,
Status__c = 'Draft',
StartDate__c = Date.today(),
ContractTerm = 12,
Legacy_Contract__c = false,
SBQQ__PreserveBundlesStructureUponRenewals__c = true
);
insert c2;
//Create Subscription
SBQQ__Subscription__c = new SBQQ__Subscription__c(
SBQQ__Account__c = a.Id,
SBQQ__Contract__c = c2.Id,
SBQQ__Product__c = sp.Id,
SBQQ__QuoteLine__c = sql.Id,
SBQQ__Quanity__c = 1,
SBQQ__ListPrice__c = 1,
SBQQ__NetPrice__c = 1,
SBQQ__CustomerPrice__c = 1,
SBQQ__RenewalQuantity__c = 1
);
insert s;
// Enque the batch
Test.startTest();
UpdateContractsStatusBatch batch = new UpdateContractsStatusBatch();
Database.executeBatch(batch);
Test.stopTest();
// Verify that the contracts were updated
List<Contract> updateContractsC1 = [SELECT Id, Status__c, SBQQ__RenewalForecast__c FROM Contract WHERE Id = :c2.Id];
System.assertEquals('Renewal Forecasted', updatedContractsC1[0].Status__c, 'Contract is updated');
System.assertEquals(true, updatedContractsC1[0].SBQQ__RenewalForecast__c, 'Renewal Forecast must be true');
// Verify that the contracts were updated
List<Contract> updateContractsC2 = [SELECT Id, Status__c, SBQQ__RenewalForecast__c FROM Contract WHERE Id = :c2.Id];
System.assertEquals('Renewal Forecasted', updatedContractsC2[0].Status__c, 'Contract is updated');
System.assertEquals(true, updatedContractsC2[0].SBQQ__RenewalForecast__c, 'Renewal Forecast must be true');
}
}
}
课程中未涵盖的线路有:
Line 10: Return;
Line 24: } catch (Exception e){
Line 30: public void execute(SchedulableContext sc) {
Database.executeBatch(new UpdateContractStatusBatch());
100% 的代码覆盖率是我所追求的。预先感谢!
if (scope.size()==0){
return;
}
这是无法访问的代码。如果剩余记录为零 - 它甚至不会调用上次的execute()。删除它。
try {
for(Contract con : scope) {
con.Status__c = 'Renewal Forecasted';
con.SBQQ__RenewalForecast__c = true;
contractsToUpdate.add(con);
}
results = Database.update(contractsToUpdate, false);
} catch (Exception e) {
System.debug('Exception in batch execute: ' + e.getMessage());
}
这也是相当遥不可及的。您使用的是不引发异常的
Database.update
版本。在更复杂的代码中,您可能会遇到一些数学错误(除以零或诸如“5 + null = 引发异常”之类的内容),但我们看到的看起来非常安全。
这些调试非常弱。一旦你过了最初的开发阶段,我就会删除它们并阅读有关
Database.RaisesPlatformEvents
的内容。
public void execute(SchedulableContext sc) {
您可以通过显式调用该方法来解决此问题,
new UpdateContractStatusBatch().execute(null);
或检查https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_scheduler中的“测试Apex Scheduler”。嗯