I have an apex class named votingRelationHandler. It is called from a trigger and works great but I am having issues with writing the test class.

Issue in the Test Class:

Non static method cannot be referenced from a static context: void votingRelationHandler.company_voting_member()

In addition I think it may also later complain about sending in values to represent the trigger.old, trigger.oldMap, trigger.new and trigger.newMap.

Is this possible to capture / emulate from the record used in test setup?


trigger votingRelation on Voting_Relation__c (before insert , after insert, before update, after update)
    votingRelationHandler handle    =   new votingRelationHandler(trigger.old, trigger.oldMap , trigger.new , trigger.newMap);

    if (trigger.isBefore)
        if (trigger.isInsert) handle.beforeInsert();
        if (trigger.isUpdate) handle.beforeUpdate();
    if (trigger.isAfter)
        if (trigger.isInsert) handle.afterInsert();
        if (trigger.isUpdate) handle.afterUpdate();

} // end trigger


public class votingRelationHandler
    final   List<Voting_Relation__c>                oldRecords;
    final   List<Voting_Relation__c>                newRecords;
    final   Map<Id, Voting_Relation__c>             oldMap;
    final   Map<Id, Voting_Relation__c>             newMap;

    public votingRelationHandler(List<Voting_Relation__c> oldRecords, Map<ID, Voting_Relation__c> oldMap , List<Voting_Relation__c> newRecords, Map<Id, Voting_Relation__c> newMap)
        this.oldRecords                         =   oldRecords;
        this.newRecords                         =   newRecords;
        this.oldMap                             =   oldMap;
        this.newMap                             =   newMap;

    public void afterInsert()

    public void company_voting_member ()
        for(Voting_Relation__c rec_VR : newRecords)
           // update account record

} // end class


private class votingRelationHandlerTest
    @testSetup static void setup()
        Account Account_VotingMember                =   TestDataFactory.createAccount_VotingMember();
        Insert  Account_VotingMember;

        Account Account_AffiliateMember             =   TestDataFactory.createAccount_AffiliateMember();
        Insert  Account_AffiliateMember;

        voting_relation__c VR_A                     =   New voting_relation__c
                voting_member__c                    =   Account_VotingMember.Id,
                company__c                          =   Account_AffiliateMember.id,
                Effective_Date__c                   =   Date.today(),
                Terminate_Date__c                   =   NULL

        insert VR_A;

    } // end setup

    static testMethod void Test()
        //How can I pass VR_A data as trigger.old, trigger.oldMap, trigger.new , trigger.newMap

        Account acc_voting                          =   [SELECT Id
                                                     FROM Account
                                                     WHERE Name     =   :PJM_GLOBAL.account_voting_member

        Account acc_affiliate                       =   [SELECT Id
                                                     FROM Account
                                                     WHERE Name     =   :PJM_GLOBAL.account_affiliate_member
        voting_relation__c VR_1                     =   [SELECT Id
                                                     FROM   voting_relation__c
                                                     WHERE  voting_member__c                =   :acc_voting.id
                                                     AND    company__c                      =   :acc_affiliate.Id
                                                     AND    Effective_Date__c               =   :PJM_GLOBAL.date_today
                                                     AND    Terminate_Date__c               =   NULL

        votingRelationHandler.company_voting_member();  <---- ISSUE IS HERE

} // end test class
  • Create an instance of votingRelationHandler. – Drew Kennedy May 18 at 16:39

When methods are not marked static, you have to first instantiate the class. In this case, you have to write it like this:

votingRelationHandler handler = new votingRelationHandler(<pass your records here>);

UPDATE: I see you updated your original code and my answer is no longer answering your question.

Your original constructor has four parameters, and you're passing only one. Make sure pass null for any parameters you don't want your controller to handle.

This are your four established parameters:

new votingRelationHandler(oldRecords, oldMap, newRecords, newMap);
| improve this answer | |
  • Thanks Sebastian. I figured it would end up being something along these lines. You have answered part I of the question and I will be sure to give you credit. Would you have the other part of the question regarding how I pass in the records? – Daryn May 18 at 16:55
  • Did you see the update I made to my answer after you edited your question ? – Sebastian Kessel May 18 at 16:56
  • Also, you updated your code but not your error message, which will be confusing for anybody else reading it... I recommend you don't update your question, rather, add more text to it so a future reader can understand what your problem is and how it was solved – Sebastian Kessel May 18 at 16:57
  • Good Point Sebastian. I was trying to update it for later reference and didn't consider that part. I restored the original for others to better follow. After I insert the record I perform a select to retrieve it but I can't seem to figure out how to pass the data to the votingRelatlionHandler. – Daryn May 18 at 17:49
  • Pass what data exactly? These are parameters you must pass to the constructor. Remember you cannot pass real "old" values here, so either you pass null or you have to exercise the trigger the way sfdcfox mentioned in his answer – Sebastian Kessel May 18 at 18:25

When unit testing triggers, is is customary to execute the trigger directly (you need this to get code coverage on the trigger itself). Since you already created the record, consider just cloning it and using that. Make sure you test both inserts and updates in different tests.

@isTest static void testInsert();
    voting_relation__c vr = [select voting_member__c, company__c, effective_date__c, teminate_date__c];
    vr = vr.clone(false, false, false); // Clears ID and audit fields //
    insert vr;
@isTest static void testUpdate();
    voting_relation__c vr = [select voting_member__c, company__c, effective_date__c, teminate_date__c];
    update vr;

Per the usual advice, make sure you're asserting to make sure that everything works as expected.

Also, you can simplify your trigger itself:

trigger votingRelation on Voting_Relation__c (before insert , after insert, before update, after update)
    votingRelationHandler handle    =   new votingRelationHandler(trigger.old, trigger.oldMap , trigger.new , trigger.newMap);
    switch on Trigger.operationType {
      when BEFORE_INSERT { handle.beforeInsert(); }
      when BEFORE_UPDATE { handle.beforeUpdate(); }
      when AFTER_INSERT { handle.afterInsert(); }
      when AFTER_UPDATE { handle.afterUpdate(); }

The reason why we want to unit test the trigger itself, and not just the calling class, is to ensure we don't hit governor limits in the face of recursive updates from processes, flows, etc.

Finally, note that testMethod is deprecated. Use @isTest instead.

| improve this answer | |
  • Hey Thanks sfdcfox. I updated the trigger and will change out all my testmethod calls. Must be been looking at older code examples. I had not considered clone before. Why do you have 3 false statements? – Daryn May 18 at 17:51

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.