You need to sign in to do that
Don't have an account?
Need Help with Apex Test Class
I wrote this trigger but don't have any idea how to start writing a test case for it. The trigger evaluates if a box is checked on a custom object. If the box is unchecked the owner defaults to the account owner at the time of creation. If the box is checked then the owner can be manually updated and the trigger isn't fired. Here is the trigger code any help would be greatly appreciated.
trigger MMOverideTrigger on RM_Requests__c (before insert, before update) {
if (Trigger.isInsert) {
RM_Requests__c[] requests = Trigger.new;
for (RM_Requests__c r :requests){
List<Account> accounts = [select OwnerId from Account where id = :r.Account__c];
for (Account a : accounts) {
r.Account_Owner_Time_of_Creation__c = a.OwnerId;
}
if(r.Account_Owner_Id_Time_of_Creation__c != null) {
if(r.Market_Manager_Overide__c == false) {
r.OwnerID = r.Account_Owner_Time_of_Creation__c;
}
}
}
}
if (Trigger.isUpdate) {
//Assign the request before and after the change into a Map
Map<Id,RM_Requests__c> newRequestMap = Trigger.newMap;
Map<Id,RM_Requests__c> oldRequestMap = Trigger.oldMap;
for(Id requestId:newRequestMap.keySet()){
RM_Requests__c myNewRequest = newRequestMap.get(requestId);
RM_Requests__c myOldRequest = oldRequestMap.get(requestId);
if ((myNewRequest.Account__c <> myOldRequest.Account__c) || (myNewRequest.Account_Owner_Time_of_Creation__c == NULL)) {
List<Account> accounts = [select OwnerId from Account where id = :myNewRequest.Account__c];
for (Account a : accounts) {
myNewRequest.Account_Owner_Time_of_Creation__c = a.OwnerId;
}
}
if(myNewRequest.Account_Owner_Id_Time_of_Creation__c != null) {
if(myNewRequest.Market_Manager_Overide__c == false) {
myNewRequest.OwnerID = myNewRequest.Account_Owner_Time_of_Creation__c;
}
}
}
All Answers
private class testTriggers {
static testMethod void testMMOverideTrigger() {
//set up a new RM_Requests__c record
RM_Requests__c rmReq = new RM_Requests__c();
// put some fields into rmReq
//create the record
insert rmReq;
// assign some value
//rmReq.___ = ;
update rmReq
}
}
Thank you! I ran this and got no code coverage. Can you see were I'm going wrong?
@istest private class MMOverideTriggerTest{
static testMethod void MMOverideTriggerTest() {
User[] users = [select id from User where IsActive= true limit 3]; User u1 = users[0]; User u2 = users[2];
RM_Requests__c rmReq = new RM_Requests__c();
rmReq.Account_Owner_Id_Time_of_Creation__c = u1.id;
rmReq.name = 'test';
rmReq.Market_Manager_Overide__c= False;
insert rmReq;
system.assertequals(u1.id,rmReq.Account_Owner_Id_Time_of_Creation__c);
Ram
insert rmReq;
rmReq.name = 'test2';
update rmReq;
Thank you!
It still says no coderage in the developer console
but in the trigger repository it has 90% coverage
Do you know why that would happen?
Sorry to bother you again. It's covering at 90% (bold lines not covered)and when I tried to deploy to production today I got this error. Any ideas?
Failure Message: "System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, MMOverideTrigger: data changed by trigger for field Owner ID: owner cannot be blank: []", Failure Stack Trace: "Class.MMOverideTriggerTest.MMOverideTriggerTest: line 11, column 1"
Trigger
trigger MMOverideTrigger on RM_Requests__c (before insert, before update) {
if (Trigger.isInsert) {
RM_Requests__c[] requests = Trigger.new;
for (RM_Requests__c r :requests){
List<Account> accounts = [select OwnerId from Account where id = :r.Account__c];
for (Account a : accounts) {
r.Account_Owner_Time_of_Creation__c = a.OwnerId;
}
if(r.Account_Owner_Id_Time_of_Creation__c != null) {
if(r.Market_Manager_Overide__c == false) {
r.OwnerID = r.Account_Owner_id_Time_of_Creation__c;
}
}
}
}
if (Trigger.isUpdate) {
//Assign the request before and after the change into a Map
Map<Id,RM_Requests__c> newRequestMap = Trigger.newMap;
Map<Id,RM_Requests__c> oldRequestMap = Trigger.oldMap;
for(Id requestId:newRequestMap.keySet()){
RM_Requests__c myNewRequest = newRequestMap.get(requestId);
RM_Requests__c myOldRequest = oldRequestMap.get(requestId);
if ((myNewRequest.Account__c <> myOldRequest.Account__c) || (myNewRequest.Account_Owner_Time_of_Creation__c == NULL)) {
List<Account> accounts = [select OwnerId from Account where id = :myNewRequest.Account__c];
for (Account a : accounts) {
myNewRequest.Account_Owner_Time_of_Creation__c = a.OwnerId;
}
}
if(myNewRequest.Account_Owner_Id_Time_of_Creation__c != null) {
if(myNewRequest.Market_Manager_Overide__c == false) {
myNewRequest.OwnerID = myNewRequest.Account_Owner_Time_of_Creation__c;
}
}
}
}
}
Class
@istest private class MMOverideTriggerTest{
static testMethod void MMOverideTriggerTest() {
RM_Requests__c rmReq = new RM_Requests__c();
rmReq.Account_Owner_Id_Time_of_Creation__c = '005600000011bkJ';
rmReq.name = 'test';
rmReq.Market_Manager_Overide__c= False;
insert rmReq;
system.assertequals('005600000011bkJ',rmReq.Account_Owner_Id_Time_of_Creation__c);
update rmReq;
}}
005600000011bkJ - is this a valid owner in your deployment Org?
Yes, thats a valid user in both dev and prod. Do I need to add an account somehwere?
Megan,
Try putting a couple of debug statements in there. I think you're trying to assign a null owner id to r.
if (Trigger.isInsert) {
RM_Requests__c[] requests = Trigger.new;
for (RM_Requests__c r :requests){
System.debug('r.Account_Owner_Time_of_Creation__c:' + r.Account_Owner_Time_of_Creation__c);
System.debug('r.Account__c:' + r.Account__c);
List<Account> accounts = [select OwnerId from Account where id = :r.Account__c];
for (Account a : accounts) {
r.Account_Owner_Time_of_Creation__c = a.OwnerId;
}
System.debug('r.Account_Owner_Time_of_Creation__c2:' + r.Account_Owner_Time_of_Creation__c);
if(r.Account_Owner_Id_Time_of_Creation__c != null) {
if(r.Market_Manager_Overide__c == false) {
r.OwnerID = r.Account_Owner_Time_of_Creation__c;
}
}
}
}
Turn on debug and see what you get for these. Also, for the future there is some optimization you need to take care of for the SOQL - you'll need to get that out of the for loop. But try it with those debug statements for now.
Ram
Thank you so much for your help. I put the debug statements in and got this error
Megan,
Can you comment out the lines that actually assign the owner id and use the debug statements as below? I believe it's crashing on the owner id assignment. Also with the test cases you have, since you're not assigning anything to Account__c in the test class, the following line will not give you any accounts.
List<Account> accounts = [select OwnerId from Account where id = :r.Account__c];
Please try the following for the trigger. I believe it should deploy fine but in a diabled fashion since it won't update the owner id. But that will give you a chance to run it and debug it.
trigger MMOverideTrigger on RM_Requests__c (before insert, before update) {
if (Trigger.isInsert) {
RM_Requests__c[] requests = Trigger.new;
for (RM_Requests__c r :requests){
System.debug('r.Account_Owner_Time_of_Creation__c:' + r.Account_Owner_Time_of_Creation__c);
System.debug('r.Account__c:' + r.Account__c);
List<Account> accounts = [select OwnerId from Account where id = :r.Account__c];
for (Account a : accounts) {
r.Account_Owner_Time_of_Creation__c = a.OwnerId;
}
if(r.Account_Owner_Id_Time_of_Creation__c != null) {
if(r.Market_Manager_Overide__c == false) {
//r.OwnerID = r.Account_Owner_Time_of_Creation__c;
System.debug('r.OwnerID = ' + r.OwnerID);
System.debug('r.Account_Owner_Time_of_Creation__c2:' + r.Account_Owner_Time_of_Creation__c);
}
}
}
}
if (Trigger.isUpdate) {
//Assign the request before and after the change into a Map
Map<Id,RM_Requests__c> newRequestMap = Trigger.newMap;
Map<Id,RM_Requests__c> oldRequestMap = Trigger.oldMap;
for(Id requestId:newRequestMap.keySet()){
RM_Requests__c myNewRequest = newRequestMap.get(requestId);
RM_Requests__c myOldRequest = oldRequestMap.get(requestId);
System.debug('myOldRequest.Account__c:' + myOldRequest.Account__c);
System.debug('myNewRequest.Account__c:' + myNewRequest.Account__c);
if ((myNewRequest.Account__c <> myOldRequest.Account__c) || (myNewRequest.Account_Owner_Time_of_Creation__c == NULL)) {
List<Account> accounts = [select OwnerId from Account where id = :myNewRequest.Account__c];
for (Account a : accounts) {
myNewRequest.Account_Owner_Time_of_Creation__c = a.OwnerId;
}
}
if(myNewRequest.Account_Owner_Id_Time_of_Creation__c != null) {
if(myNewRequest.Market_Manager_Overide__c == false) {
//myNewRequest.OwnerID = myNewRequest.Account_Owner_Time_of_Creation__c;
System.debug('myNewRequest.OwnerID = ' + myNewRequest.OwnerID);
System.debug('myNewRequest.Account_Owner_Time_of_Creation__c2:' + myNewRequest.Account_Owner_Time_of_Creation__c);
}
}
}
}
}
Thank you. I used the trigger with the original class and am only getting 40% coverage. I think changed it to the below class to be more generic and i'm not getting anything.
I think it's not deploying becuase the owner ID = account id at time of creation but the owner id can not be null and the account id at time of creation could be if the record was created before the field was added. I just don't know how to fix it.
Hi Megan,
Can you please try this?
Create an account explicitly in your test class and use it:
Just copy this entire snippet into your test class and try it.
@istest public class MMOverideTriggerTest2{
static testMethod void MMOverideTriggerTest(){
Account acct = new Account();
acct.Name = 'Test account';
insert acct;
RM_Requests__c rmReq = new RM_Requests__c();
rmReq.Account_Owner_Id_Time_of_Creation__c= acct.id;
rmReq.name = 'test';
rmReq.Market_Manager_Overide__c = False;
//rmReq.ownerID = a1.id;
insert rmReq;
system.assertequals(acct.id,rmReq.Account_Owner_Id_Time_of_Creation__c);
rmReq.Market_Manager_Overide__c= True;
//rmReq.Account_Owner_Id_Time_of_Creation__c = null;
//rmReq.ownerid = a1.id;
//rmreq.account__c=a1.name;
update rmReq;
system.assertequals(acct.id, rmReq.Account_Owner_Id_Time_of_Creation__c);
}}
Ram
Thank you! It's still only at 40% : ( All the mapping marts in the trigger are failing
Thanks,
Ram
sorry! The account owner ID time of creation is populated off a workflow rule that pulls the account owner id...could that be the problem?
trigger MMOverideTrigger on RM_Requests__c (before insert, before update) {
if (Trigger.isInsert) {
RM_Requests__c[] requests = Trigger.new;
for (RM_Requests__c r :requests){
System.debug('r.Account_Owner_Time_of_Creation__c:' + r.Account_Owner_Time_of_Creation__c);
System.debug('r.Account__c:' + r.Account__c);
List<Account> accounts = [select OwnerId from Account where id = :r.Account__c];
for (Account a : accounts) {
r.Account_Owner_Time_of_Creation__c = a.OwnerId;
}
System.debug('r.Account_Owner_Time_of_Creation__c2:' + r.Account_Owner_Time_of_Creation__c);
if(r.Account_Owner_Id_Time_of_Creation__c != null) {
if(r.Market_Manager_Overide__c == false) {
r.OwnerID = r.Account_Owner_id_Time_of_Creation__c;
}
}
}
}
if (Trigger.isUpdate) {
//Assign the request before and after the change into a Map
Map<Id,RM_Requests__c> newRequestMap = Trigger.newMap;
Map<Id,RM_Requests__c> oldRequestMap = Trigger.oldMap;
for(Id requestId:newRequestMap.keySet()){
RM_Requests__c myNewRequest = newRequestMap.get(requestId);
RM_Requests__c myOldRequest = oldRequestMap.get(requestId);
if ((myNewRequest.Account__c <> myOldRequest.Account__c) || (myNewRequest.Account_Owner_Time_of_Creation__c == NULL)) {
List<Account> accounts = [select OwnerId from Account where id = :myNewRequest.Account__c];
for (Account a : accounts) {
myNewRequest.Account_Owner_Time_of_Creation__c = a.OwnerId;
}
}
if(myNewRequest.Account_Owner_Id_Time_of_Creation__c != null) {
if(myNewRequest.Market_Manager_Overide__c == false) {
myNewRequest.OwnerID = myNewRequest.Account_Owner_Time_of_Creation__c;
}
}
}
}
}
WF rule
The WF rule populates the account owner ID time of creation with the account owner ID from the account object at creation or update. The account owner time of creation is a lookup field that populates that account owner name based on the id.
It was supposed to complement it. If I disable the WF the account owner time of creation still populates but the ID does not.
Megan,
It seems to me you're using Account_Owner_Id_Time_of_Creation__c and Account_Owner_Time_of_Creation__c very much alike.
Can you please post the field definitions of both the fields?
We may need to tweak the trigger based on the exact definitions of these.
Sure. They are estentially the same. The same value should always be in both of them the accoutn owner id at time of creation field will just have the ID oc the accoutn owner and the account owner at time of creation will have the name of the owner that corresponds with the id. Does that make sense?
Yes thats correct. Right now the account owner time of creation is opperating as a lookup
ok - I think the two are really serving the same purpose and probably one of'em could be eliminated. In any case, please try the following for your test class:
@istest public class MMOverideTriggerTest2{
static testMethod void MMOverideTriggerTest(){
Account a1 = new Account();
a1.Name = 'Test Account';
insert a1;
a1 = [Select Id, name, OwnerId from Account where Id = :a1.id];
RM_Requests__c rmReq = new RM_Requests__c();
rmReq.Account_Owner_Id_Time_of_Creation__c = a1.OwnerId;
rmReq.name = 'test';
rmReq.Market_Manager_Overide__c = False;
rmreq.account__c = a1.id;
insert rmReq;
system.assertequals(a1.id,rmReq.Account_Owner_Id_Time_of_Creation__c);
rmReq.Market_Manager_Overide__c= True;
rmReq.Account_Owner_Id_Time_of_Creation__c = null;
rmreq.account__c = a1.id;
update rmReq;
system.assertequals(a1.id,rmReq.Account_Owner_Id_Time_of_Creation__c);
}
}
Thanks,
Ram
Thank you! That seemed to work better 86% of the code was covered. It still failed when I tried to deploy to production. I got this message.
Failure Message: "System.AssertException: Assertion Failed: Expected: 0016000000pt8i5AAA, Actual: 00560000001qO3jAAE", Failure Stack Trace: "Class.MMOverideTriggerTest2.MMOverideTriggerTest: line 20, column 1"
Line 30-32 were not covered
Just change both your asserts to
system.assertequals(a1.Ownerid, rmReq.Account_Owner_Id_Time_of_Creation__c);
Yep I figured that out and it worked! Thank you so much for all your help!
best,
Ram
Hi, One more question. The trigger works great as it is now, but it needs to be changed so it only fires after "submit for approval" has been hit. Is there a way to do that?
The trigger will fire unconditionally for the context it is set for.
I'm not entirely sure there's a way to distinguish within the trigger whether this was done on a submit for approval vs otherwise. There may be some data elements on the trigger that come in on a Submit for Approval that you may need to look for and examine within the trigger and then conditionally execute any changes within the trigger, Unfortunately I don't know off hand what you will get for a Submit for Approval scenario. I'd play around with updating that object records and see what is received in the trigger for the different scenarios,
Ram
Thanks. I tried a couple different things with if statements (where current_status__r=submitted etc) and nothing working. I haven't come across anything on line either so I just thought I would ask. Thanks!