0

I'm trying to test for a trigger that insert a calculated duration of Event after insert/update of A Event record. For example, the trigger fills an integer representing hours, calculated from StartDateTime and EndDateTime of the subject Event record, to DurationInHours__c field.

The problem is that DurationInHours__c is null when System.assertEquals is executed. Error message says 'System.AssertException: Assertion Failed: Expected: 1, Actual: null'. Note that event duration is set to be 1 hour.

Please help me out.

Test code:

@isTest
public class TestUpdateDuration {
    @isTest static void TestUpdateDuration() {
        // Test data setup
        // Create an event with 1 hour duration
        User myUser =[select id from User where Email = 'foobar@mail.com'];

        Datetime myStart = Datetime.newInstance(2019, 9,17, 7,0,0);
        Datetime myEnd = Datetime.newInstance(2019, 9,17, 8,0,0);
        Event ev = new Event(
                             StartDateTime = myStart,
                             EndDateTime = myEnd 
                            );
        insert ev;

        // Verify 
        // In this case '1' should be added to DurationInHours__c field by the trigger,
        // so verify if it is correct
        System.assertEquals(1, ev.DurationInHours__c);
    }    
}

Trigger: Event record will have an event duration value in DurationInHours__c after update/insert. I manually check that a value is inserted and it was ok.

trigger updateDuration on Event (after update, after insert) {
    List<Event> listEvents = new List<Event>();

    for ( Event e : Trigger.new ) {
        Event updateE = [select id, EndDateTime, StartDateTime, DurationInHours__c, DurationInMinutes, IsAllDayEvent from Event where id = :e.id];

        // How many days will that event last?
        Long msecStart = updateE.StartDateTime.getTime();
        Long msecEnd = updateE.EndDateTime.getTime();

        Long msecDuration = msecEnd - msecStart;
        Long elapsedHours = 0;
        if(updateE.IsAllDayEvent) {
            elapsedHours = 8;
        } else {
            elapsedHours = ((msecDuration / 1000) / 60) / 60;
        }

        if(updateE.DurationInHours__c != elapsedHours) {
           updateE.DurationInHours__c = elapsedHours;
           listEvents.add(updateE);
        }    
    }
    update listEvents;
}
  • Is there any reason you're using an after trigger rather than a before trigger? – Nick Cook Sep 17 at 5:48
  • That's because I want to add a value to a certain field of the record that is just updated or inserted. So execution timing should be after the record is actually updated or inserted. Does this make sense?? – masato maeyama Sep 17 at 7:15
0

Welcome to Salesforce StackExchange.

the test method creates an Event and inserts it into the database temporarily. So for retrieving the other value you should write the SOQL on Event to get the value of other Feild.

Please Read Apex Test Class Documentation.

So changes in your code need to do.

System.assertEquals(1,[Select Id, DurationInHours__c From Event Where Id = : 'eventId'].DurationInHours__c);

Important Tips

  • Please use @testSetup method to create test data, and get the data in the test method using SOQL. @testSetup Document.
  • I seeing you are using SOQL inside for loop in your trigger, which is an impact with large data means trigger are not bulkify, due to governer limits. Please see Test bulky trigger Document
  • Thank you for kind comments, Sarvesh. I successfully rewrote the trigger and test and the test passed. – masato maeyama Sep 17 at 7:09
  • @masatomaeyama Hope you removed the query from inside the loop as likely to break your org in the future; the data you are querying is already available to you in the Trigger fields. – Keith C Sep 17 at 7:36
  • @Sarvesh I modified the code like below. This retrieves ids before loop for iteration. But do you mean the retrieval is not necessary and the ids can be reached from Trigger object? Like how? I would be greatly appreciated if you could suggest how to do it. java trigger updateDuration on Event (after update, after insert) { Set<ID> ids = Trigger.newMap.KeySet(); List<Event> listEvents = [select id, EndDateTime, StartDateTime, DurationInHours__c, IsAllDayEvent from Event where id = :ids]; for ( Event e : listEvents ) { – masato maeyama Sep 17 at 7:46
  • No need of SOQL use newMap.values() for(Event evt : Trrigger.newMap.Values()) – Sarvesh Sep 19 at 6:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.