你好
我正在Salesforce内部为trigger进行单元测试,我不断遇到一个似乎无法解决的错误,所以我希望有更多经验的人能帮助我回到正轨。我已经在Google上搜索过很多次了,我的代码结构也被弄乱了,但我找不到解决方案。
目的:
我的任务是编写一个触发器,该触发器将处理维护每个开发人员的案例排名所需的逻辑。每个开发人员都被分配了案例,这些案例可能有也可能没有由业务确定的优先级。每个开发人员在任何时候只能优先考虑10个案例。任何其他案例在排名字段中都只有空值。如果插入、更新或删除了具有排名的案例,那么分配给该开发人员的所有其他案例都必须相应地自动更新。任何排名高于10的案例都将被取消。
问题:
我已经完成了触发器和触发器处理程序类,现在我正在编写单元测试来覆盖所有单元测试。当我完成第一个单元测试方法时,出现了一个引用工作流问题的错误。我发现并纠正了这个问题,但在我完成了第二个单元测试方法之后,我又出现了同样的错误。我可以注释掉这两个方法中的任何一个,也可以注释掉其他过程,但每当我将它们一起运行时,第一个过程会通过,第二个过程会失败,并出现相同的原始错误。
错误:
系统。DmlException:更新失败。第0行的第一个异常;第一个错误:CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY,工作流或审批字段更新在保存此记录时导致错误。联系您的管理员解决它。开发人员分配的电子邮件:无效的电子邮件地址:假:[]
代码:
触发代码-
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/09/15
* @brief: This is a trigger for the Case object that will modify the rank of the Cases
* assigned to the developer based on a priority set by the Administrator.
***************************************************************************************/
trigger CaseRankTrigger on Case (before insert, before update, before delete) {
// trigger level variables
private static Boolean firstRun = true;
private RecordType ticketRecordType = [SELECT Id FROM RecordType WHERE SobjectType = 'Case' AND Name = 'Salesforce Service Ticket' LIMIT 1];
private List<Case> newTrigger = trigger.new;
private List<Case> currentTrigger = trigger.old;
private List<Case> qualifiedNewCases = new List<Case>();
private List<Case> qualifiedCurrentCases = new List<Case>();
// makes sure that the trigger only runs once
if (firstRun) {
firstRun = false;
// populate trigger Case lists
qualifyCases();
if (qualifiedNewCases.size() == 1 || qualifiedCurrentCases.size() == 1) {
// the CaseRankTriggerHandler constructor method takes (List<Case>, List<Case>, String)
if (trigger.isInsert) CaseRankTriggerHandler handler = new CaseRankTriggerHandler(qualifiedNewCases, qualifiedCurrentCases, 'Insert'); // if a new Case is being inserted into the database
if (trigger.isUpdate) CaseRankTriggerHandler handler = new CaseRankTriggerHandler(qualifiedNewCases, qualifiedCurrentCases, 'Update'); // if an existing Case is being updated
if (trigger.isDelete) CaseRankTriggerHandler handler = new CaseRankTriggerHandler(qualifiedNewCases, qualifiedCurrentCases, 'Delete'); // if an existing Case is deleted from the database
}
}
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/24/15
* @brief: The qualifyCases method populates a list of Cases for each trigger
* that are of the Salesforce Service Ticket record type only.
* @return: Void
***************************************************************************************/
public void qualifyCases() {
if (newTrigger != null ) {
for (Case c : newTrigger) {
if (c.recordTypeId == ticketRecordType.Id) {
qualifiedNewCases.add(c);
}
}
}
if (currentTrigger != null) {
for (Case c : currentTrigger) {
if (c.recordTypeId == ticketRecordType.Id) {
qualifiedCurrentCases.add(c);
}
}
}
}
}
触发器处理程序代码-
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/09/15
* @brief: This is a Case object trigger handler class that provides logic to the CaseRankTrigger for manipulating
* the ranks of all Cases assigned to a developer based on a priority that is set by an Administrator.
***************************************************************************************/
public with sharing class CaseRankTriggerHandler {
// class level variables
private static Boolean firstRun = true;
private static Boolean modify = false;
private static Integer MAX = 10;
private static Integer MIN = 1;
private List<Case> newTrigger {get; set;}
private List<Case> currentTrigger {get; set;}
private List<Case> cases {get; set;}
private List<Case> newList {get; set;}
private List<Case> currentList {get; set;}
private String developer {get; set;}
private Decimal newRank {get; set;}
private Decimal currentRank {get; set;}
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/16/15
* @brief: Class constructor method.
* @return: Void
***************************************************************************************/
public CaseRankTriggerHandler(List<Case> newT, List<Case> oldT, String type) {
if (firstRun) { // makes sure that the trigger only runs once
firstRun = false;
InitializeTrigger(newT, oldT, type); // initializes the trigger
if (developer != null) { // skips trigger if DML is performed on a Case with no developer assigned
ModificationCheck(type); // determines if Cases need to be modified
if (modify) ModificationLogic(type); // modifies Cases if needed
}
}
}
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/16/15
* @brief: The InitializeTrigger method initializes the handler class based on the type of trigger fired.
* @return: Void
***************************************************************************************/
private void InitializeTrigger(List<Case> newT, List<Case> oldT, String type) {
if (type == 'Insert') {
this.newTrigger = newT;
this.developer = newTrigger[0].Resource_Assigned__c;
this.newRank = newTrigger[0].Case_Rank__c;
this.newList = [SELECT Subject, CaseNumber, Case_Rank__c FROM Case WHERE Resource_Assigned__c = :developer AND Case_Rank__c != null AND Case_Rank__c = :newRank ORDER BY Case_Rank__c];
} else if (type == 'Update') {
this.newTrigger = newT;
this.currentTrigger = oldT;
this.developer = newTrigger[0].Resource_Assigned__c;
this.newRank = newTrigger[0].Case_Rank__c;
this.currentRank = currentTrigger[0].Case_Rank__c;
this.newList = [SELECT Subject, CaseNumber, Case_Rank__c FROM Case WHERE Resource_Assigned__c = :developer AND Case_Rank__c != null AND Case_Rank__c = :newRank ORDER BY Case_Rank__c];
this.currentList = [SELECT Subject, CaseNumber, Case_Rank__c FROM Case WHERE Resource_Assigned__c = :developer AND Case_Rank__c != null AND Case_Rank__c = :currentRank ORDER BY Case_Rank__c];
} else if (type == 'Delete') {
this.currentTrigger = oldT;
this.developer = currentTrigger[0].Resource_Assigned__c;
this.currentRank = currentTrigger[0].Case_Rank__c;
}
}
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/16/15
* @brief: The ModificationCheck method ensures various conditions are met, depending on the type
* of trigger that was fired, before modifying the ranks of the Cases assigned to the developer.
* @return: Void
***************************************************************************************/
private void ModificationCheck(String type) {
if (type == 'Insert') {
// the Case being inserted has a new rank not equal to null and if the assigned developer already has a Case with the
// same rank as the new rank, we will proceed to modification, if not the record will be inserted without modification.
if (newRank != null && !newList.isEmpty()) {
modify = true;
}
} else if (type == 'Update') {
// if the Case being updated has ranks with different values in both triggers we will proceed to the next check, if not the record is updated without modification.
if (newRank != currentRank) {
// if the Case being updated has a (new rank equal to null and a current rank not equal to 10) or
// if the Case being updated has a new rank not equal to null, we will proceed to the next check,
// if not the record is updated without modification.
if ((newRank == null && currentRank != 10) || newRank != null) {
// if the assigned developer on the Case being updated already has a Case with the same rank as the new or current rank, we will proceed to modification,
// if not the record is updated without modification.
if (!newList.isEmpty() || !currentList.isEmpty()) {
modify = true;
}
}
}
} else if (type == 'Delete') {
// if the Case being deleted has current rank not equal to null, we will proceed to modification, if not the record is deleted without modification.
if (currentRank != null) {
modify = true;
}
}
}
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/16/15
* @brief: If a Case rank needs to be updated the ModificationLogic method calls the appropriate
* computation method based on trigger type and the values of newRank and currentRank.
* @return: Void
***************************************************************************************/
private void ModificationLogic(String type) {
if (type == 'Insert') {
for (Case c : newTrigger) {
// calls the IncreaseCaseRank method and passes it a list of Cases that are assigned to the developer that have a rank greater than or equal to the new rank.
IncreaseCaseRank([SELECT Subject, CaseNumber, Case_Rank__c FROM Case WHERE Id NOT IN :newTrigger AND Resource_Assigned__c = :developer AND Case_Rank__c >= :newRank ORDER BY Case_Rank__c]);
}
} else if (type == 'Update') {
for (Case c : newTrigger) {
if (currentRank == null) {
// if the current rank is null - calls the IncreaseCaseRank method and passes it a list of Cases that are assigned to the developer that have a rank greater than or equal to the new rank.
IncreaseCaseRank([SELECT Subject, CaseNumber, Case_Rank__c FROM Case WHERE Id NOT IN :newTrigger AND Resource_Assigned__c = :developer AND Case_Rank__c >= :newRank ORDER BY Case_Rank__c]);
} else if (newRank == null) {
// if the new rank is null - calls the DecreaseCaseRank method and passes it a list of Cases that are assigned to the developer that have a rank greater than the current rank.
DecreaseCaseRank([SELECT Subject, CaseNumber, Case_Rank__c FROM Case WHERE Id NOT IN :newTrigger AND Resource_Assigned__c = :developer AND Case_Rank__c > :currentRank ORDER BY Case_Rank__c]);
} else if (newRank > currentRank) {
// if the new rank is greater than the current rank - calls the DecreaseCaseRank method and passes it a list of Cases that are assigned to the developer that have a rank less than or equal to the new rank and greater than to the current rank.
DecreaseCaseRank([SELECT Subject, CaseNumber, Case_Rank__c FROM Case WHERE Id NOT IN :newTrigger AND Resource_Assigned__c = :developer AND (Case_Rank__c <= :newRank AND Case_Rank__c > :currentRank) ORDER BY Case_Rank__c]);
} else if (newRank < currentRank) {
// if the new rank is less than the current rank - calls the IncreaseCaseRank method and passes it a list of Cases that are assigned to the developer that have a rank a.
IncreaseCaseRank([SELECT Subject, CaseNumber, Case_Rank__c FROM Case WHERE Id NOT IN :newTrigger AND Resource_Assigned__c = :developer AND (Case_Rank__c >= :newRank AND Case_Rank__c < :currentRank) ORDER BY Case_Rank__c]);
}
}
} else if (type == 'Delete') {
for (Case c : currentTrigger) {
// calls the DecreaseCaseRank method and passes it a list of Cases that are assigned to the developer that have a rank greater than the current rank.
DecreaseCaseRank([SELECT Subject, CaseNumber, Case_Rank__c FROM Case WHERE Id NOT IN :currentTrigger AND Resource_Assigned__c = :developer AND Case_Rank__c > :currentRank ORDER BY Case_Rank__c]);
}
}
}
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/16/15
* @brief: The DecreaseCaseRank method provides the logic required to properly
* decrease or null out the ranks of the Cases assigned the the developer.
* @return: Void
***************************************************************************************/
private void DecreaseCaseRank(List<Case> cases) {
// if the list of Cases passed in by the ModificationLogic method isn't empty then it will iterate through the
// list and decrease their ranks by 1 or null out the rank if it is not within the acceptable limits (1-10).
if (!cases.isEmpty()) {
for (Case c : cases) {
if (c.Case_Rank__c >= 1 && c.Case_Rank__c <= 10) {
c.Case_Rank__c = c.Case_Rank__c - 1;
} else {
c.Case_Rank__c = null;
}
}
update cases;
}
return;
}
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/16/15
* @brief: The IncreaseCaseRank method provides the logic required to properly
* increase or null out the ranks of the Cases assigned the the developer.
* @return: Void
***************************************************************************************/
private void IncreaseCaseRank(List<Case> cases) {
// if the list of Cases passed in by the ModificationLogic method isn't empty then it will iterate through the
// list and increase their ranks by 1 or null out the rank if it is not within the acceptable limits (1-10).
if (!cases.isEmpty()) {
for (Case c : cases) {
if (c.Case_Rank__c >= 1 && c.Case_Rank__c < 10) {
c.Case_Rank__c = c.Case_Rank__c + 1;
} else {
c.Case_Rank__c = null;
}
}
update cases;
}
return;
}
}
触发器处理程序测试代码-
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/24/15
* @brief: This is the test class for the CaseRankTriggerHandler class
***************************************************************************************/
@isTest
public with sharing class CaseRankTriggerHandlerTest {
// class level variables
static User testRequestor = createTestRequestor();
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/24/15
* @brief: The InsertCase_NewRankNull test method ensures that the insert functionality of the
* CaseRankTrigger is working as intended when a new Case is inserted with a null rank.
***************************************************************************************/
@isTest
static void InsertCase_NewRankNull() {
// creates the initial case load for 'Test Developer' by passing in a list of integers that will become the ranks for the cases
createDeveloperCase_Multiple(new List<Integer> {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
// starting the test by inserting a new Case with a null rank
Test.startTest();
createDeveloperCase_Single('Null', null);
Test.stopTest();
// queries the system to create a map of Cases assigned to 'Test Developer' that are keyed by Rank with Subject as the value
Map<Decimal, String> caseMap = createCaseMap();
// system asserts to ensure that Cases are in the proper order
System.assertEquals('Test Case (1)', caseMap.get(1), 'Test Developer should have \'Test Case (1)\' as rank 1 but instead has ' + caseMap.get(1));
System.assertEquals('Test Case (2)', caseMap.get(2), 'Test Developer should have \'Test Case (2)\' as rank 2 but instead has ' + caseMap.get(2));
System.assertEquals('Test Case (3)', caseMap.get(3), 'Test Developer should have \'Test Case (3)\' as rank 3 but instead has ' + caseMap.get(3));
System.assertEquals('Test Case (4)', caseMap.get(4), 'Test Developer should have \'Test Case (4)\' as rank 4 but instead has ' + caseMap.get(4));
System.assertEquals('Test Case (5)', caseMap.get(5), 'Test Developer should have \'Test Case (5)\' as rank 5 but instead has ' + caseMap.get(5));
System.assertEquals('Test Case (6)', caseMap.get(6), 'Test Developer should have \'Test Case (6)\' as rank 6 but instead has ' + caseMap.get(6));
System.assertEquals('Test Case (7)', caseMap.get(7), 'Test Developer should have \'Test Case (7)\' as rank 7 but instead has ' + caseMap.get(7));
System.assertEquals('Test Case (8)', caseMap.get(8), 'Test Developer should have \'Test Case (8)\' as rank 8 but instead has ' + caseMap.get(8));
System.assertEquals('Test Case (9)', caseMap.get(9), 'Test Developer should have \'Test Case (9)\' as rank 9 but instead has ' + caseMap.get(9));
System.assertEquals('Test Case (10)', caseMap.get(10), 'Test Developer should have \'Test Case (10)\' as rank 10 but instead has ' + caseMap.get(10));
System.assertEquals('Test Case (Null)', caseMap.get(null), 'Test Developer should have \'Test Case (Null)\' as rank null but instead has ' + caseMap.get(null));
delete [SELECT Id FROM Case WHERE Resource_Assigned__c = 'Test Developer'];
}
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/24/15
* @brief: The InsertCase_NewRankNotNull test method ensures that the insert functionality of the
* CaseRankTrigger is working as intended when a new Case is inserted with a rank that is not null.
***************************************************************************************/
@isTest
static void InsertCase_NewRankNotNull() {
// creates the initial case load for 'Test Developer' by passing in a list of integers that will become the ranks for the cases
createDeveloperCase_Multiple(new List<Integer> {1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
// starting the test by inserting a new Case with a null rank
Test.startTest();
createDeveloperCase_Single('NewNotNull', 4);
Test.stopTest();
// queries the system to create a map of Cases assigned to 'Test Developer' that are keyed by Rank with Subject as the value
Map<Decimal, String> caseMap = createCaseMap();
// system asserts to ensure that Cases are in the proper order
System.assertEquals('Test Case (1)', caseMap.get(1), 'Test Developer should have \'Test Case (1)\' as rank 1 but instead has ' + caseMap.get(1));
System.assertEquals('Test Case (2)', caseMap.get(2), 'Test Developer should have \'Test Case (2)\' as rank 2 but instead has ' + caseMap.get(2));
System.assertEquals('Test Case (3)', caseMap.get(3), 'Test Developer should have \'Test Case (3)\' as rank 3 but instead has ' + caseMap.get(3));
System.assertEquals('Test Case (NewNotNull)', caseMap.get(4), 'Test Developer should have \'Test Case (NewNotNull)\' as rank 4 but instead has ' + caseMap.get(4));
System.assertEquals('Test Case (4)', caseMap.get(5), 'Test Developer should have \'Test Case (4)\' as rank 5 but instead has ' + caseMap.get(5));
System.assertEquals('Test Case (5)', caseMap.get(6), 'Test Developer should have \'Test Case (5)\' as rank 6 but instead has ' + caseMap.get(6));
System.assertEquals('Test Case (6)', caseMap.get(7), 'Test Developer should have \'Test Case (6)\' as rank 7 but instead has ' + caseMap.get(7));
System.assertEquals('Test Case (7)', caseMap.get(8), 'Test Developer should have \'Test Case (7)\' as rank 8 but instead has ' + caseMap.get(8));
System.assertEquals('Test Case (8)', caseMap.get(9), 'Test Developer should have \'Test Case (8)\' as rank 9 but instead has ' + caseMap.get(9));
System.assertEquals('Test Case (9)', caseMap.get(10), 'Test Developer should have \'Test Case (9)\' as rank 10 but instead has ' + caseMap.get(10));
System.assertEquals('Test Case (10)', caseMap.get(null), 'Test Developer should have \'Test Case (10)\' as rank null but instead has ' + caseMap.get(null));
delete [SELECT Id FROM Case WHERE Resource_Assigned__c = 'Test Developer'];
}
/***************************************************************************************
* @author: Michael *REDACTED*
* @email: michael.*REDACTED*@*REDACTED*.com
* @date: 11/24/15
* @brief: The createCaseMap method queries all the developers Cases then creates a map
* keyed by Rank with the Subject as the value. This map will be used to ensure that
* the Cases are in the proper order after any DML has been performed on a Case.
* @return: Map<Decimal, String>
***************************************************************************************/
static Map<Decimal, String> createCaseMap() {
List<Case> caseList = [SELECT Case_Rank__c, Subject FROM Case WHERE Resource_Assigned__c = 'Test Developer' ORDER BY Case_Rank__c];
Map<Decimal, String> caseMap = new Map<Decimal, String>();
for (Case c : caseList) {
caseMap.put(c.Case_Rank__c, c.Subject);
}
return caseMap;
}
/***************************************************************************************
* TEST DATA SECTION - Refactor out of test class after creating Test Data Factory
***************************************************************************************/
static User createTestRequestor() {
Profile testProfile = [SELECT Id from Profile where Name = 'Standard User'];
User requestor = new User(FirstName = 'Test', LastName = 'Requestor', Alias = 'Test.Req', Email = 'newtestrequestor@null.com', UserName = 'newtestrequestor@null.com', ProfileId = testProfile.Id,
TimeZoneSidKey = 'America/Los_Angeles', LocaleSidKey = 'en_US', EmailEncodingKey = 'UTF-8', LanguageLocaleKey = 'en_US');
insert requestor;
return requestor;
}
static List<Case> createDeveloperCase_Multiple(List<Integer> ranks) {
List<Case> developerCaseLoad = new List<Case>();
Case developerCase;
Integer count = 0;
for (Integer rank : ranks) {
count++;
developerCase = new Case(Subject = 'Test Case (' + count + ')', Service_Request_Type__c = 'Development', Requestor__c = testRequestor.Id, Description = 'Foo', Business_Value_of_Change__c = 'Bar',
Business_Area__c = 'Warranty', Requested_Implementation_Date__c = Date.today(), Resource_Assigned__c = 'Test Developer', Resource_Assigned_Email__c = 'newtestdeveloper@null.com', Case_Rank__c = rank);
developerCaseLoad.add(developerCase);
}
for (Case c : developerCaseLoad) {
}
upsert developerCaseLoad;
return developerCaseLoad;
}
static Case createDeveloperCase_Single(String name, Integer rank) {
Case developerCase = new Case(Subject = 'Test Case (' + name + ')', Service_Request_Type__c = 'Development', Requestor__c = testRequestor.Id, Description = 'Foo', Business_Value_of_Change__c = 'Bar',
Business_Area__c = 'Warranty', Requested_Implementation_Date__c = Date.today(), Resource_Assigned__c = 'Test Developer', Case_Rank__c = rank);
upsert developerCase;
return developerCase;
}
}
工作流代码-这不是我写的,但单击查看图片
CASE( Resource_Assigned__c ,
"Kimberly REDACTED","foo@bar.com",
"Josh REDACTED","foo@bar.com",
"Robert REDACTED","foo@bar.com",
"Jose REDACTED","foo@bar.com",
"Ryan REDACTED","foo@bar.com",
"Lloyd REDACTED","foo@bar.com",
"Nathan REDACTED","foo@bar.com",
"Amber REDACTED","foo@bar.com",
"Ora REDACTED","foo@bar.com",
"Jason REDACTED","foo@bar.com",
"Shalini REDACTED","foo@bar.com",
"Siva REDACTED","foo@bar.com",
"Quinn REDACTED","foo@bar.com",
"Adrienne REDACTED","foo@bar.com",
"Vasantha REDACTED","foo@bar.com",
"Michael REDACTED","foo@bar.com",
"Sudheera REDACTED","foo@bar.com",
"Test Developer","newtestdeveloper@null.com",
"false")
我真的很感谢你们在这件事上能给我的任何帮助<向迈克尔问好
这是我所做的来解决我的问题。
我重构了测试并删除了两个测试开发人员的创建。相反,我抓取了我们使用的下拉列表中包含的两个随机开发人员,然后在测试中使用了这些开发人员。
由于一切都是这样设置的,我不需要使用生产数据(SeeAllData=true)来进行修复,在更改代码后,我再也没有遇到过测试问题。
下面是我的顶点触发器。我是一名初学者,正在尝试编写其测试类,但不断出现错误“System.DmlException:Insert失败。第0行出现第一个异常;第一个错误:REQUIRED\u FIELD\u MISSING,错误:只有在产品相关列表上为此opportunity选择了价格手册,才能选择产品。:[]”。 在Opportunity上触发TrgrOptyHighestCustmorePric
大家好, 我正在尝试为我帮助编写的触发器编写一个测试类。触发器使用名为trigger\u help\u c的字段,该字段是通过添加opportunity Type和Account ID派生的公式字段,如果在过去90天内已在该帐户上创建了该类型的opportunity,则在插入之前激发。除非配置文件是系统管理员。这是我的触发器: 我在写测试课时遇到了困难,我像往常一样不知所措。我写了以下内容,但我不
我已在Salesforce APEX中记录了触发器。它工作正常。 触发器代码为: 现在我正在尝试为它的测试类编写代码。它在线上给出错误,说对象无法解析为字符串。 测试等级代码为: 期待找到解决方案。任何帮助都将不胜感激。 谢谢
我已经为此发疯了。我的IF循环中没有任何东西通过我的测试类触发,我不知道为什么。我在网上阅读了很多,看起来我做的事情是正确的,但它仍然没有解决我的代码覆盖率。这是运行的最后一行:如果(isIn==True){ 之后我无法让任何东西在IF循环中运行,我已经颠倒了逻辑,它仍然无法运行。我觉得当有人指出它时,我会踢自己,但这是我的代码: } 这是我的测试类:
我在Apex中有一个触发器。如何编写检查触发器是否被调用的单元测试?
问题内容: 假设我有一个类似 测试此bean实际上将在其指定日期( 即 最接近每月15日的工作日)触发的最佳方法是什么? 更新 :这应该是一个单元测试,所以我不会启动虚拟机或更改系统时间。 问题答案: 首先,没有必要进行自我测试。它是spring框架的一部分,已经过测试。 更好的测试可能是测试您的cron表达式是否符合您的期望。这里的一种选择是使用Quartz的类。给定一个对象,您可以调用,该表达