function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
MattiasNordin.ax607MattiasNordin.ax607 

How to write a test class for an apex trigger

Hi,

 

Can someone explain to me how to write a test class for an apex trigger like the following one?

 

trigger trgMnUpdateContactFieldsFromUserTable on Contact (before update, before insert) {

    Set<Id> userIds = new Set<Id>();
    for (Contact a : Trigger.new)
        userIds.add(a.OwnerId);
    
    // Query the User table for the associated fields you need and place in a map.
    Map<Id, User> fields = new Map<Id, User>([select Name, User_Region__c from User where id in :userIds]);
    
    // Now use the map to set the appropriate fields on every Account processed by the trigger.
    for (Contact a : Trigger.new) {
        
        // OWNER NAME FROM USER TO ACCOUNT
        a.Owner_name_txt__c = fields.get(a.OwnerId).Name;

        // OWNER REGION FROM USER TO ACCOUNT
        a.Owner_region__c = fields.get(a.OwnerId).User_Region__c;

    }    
}

 

Pradeep_NavatarPradeep_Navatar

You can build a test method like the sample trigger given below :

 

            @isTest

                private class sampleTestClass

                {

                     public static testMethod void testocc()

                  {

                    User u = [select name,Id,User_Region_c,profileId=:[select Id from profile where name='system administrator'].Id  limit 1];

                    system.runAs(u)

                   {

                                Account acc = new Account(name = "testaccount");

                                insert acc;

 

                                Contact con = new Contact(AccountId = acc.id,lastname = "testdata" , firstname ="testdata1",OwnerId = Userinfo.getUserid(),Owner_name_txt__c = “textdata”, Owner_region__c = "testregion");

                                insert con;

                   }

                }

           }

 

Hope this helps.

Mattias NordinMattias Nordin

Thanks for your reply. Im trying to learn how to write my own apex triggers to do really small things like copying a value from obj a to obj b. Im a total beginner to this environment so please be detailed.

 

Should your code be saved as a new Apex class or can you add it directly on my trigger?

MattiasNordin.ax607MattiasNordin.ax607

I dont understand how the test knows what trigger to test. Can someone explain how the test class and the object to verify hangs together.

 

Do you only write one test class that updates/tests all classes/triggers or do you write several smaller one?

 

There is a lot of information out there but there is no guide for dummies like me.

MattiasNordin.ax607MattiasNordin.ax607

 

@isTest
private class TheTestClass { 
   
	public static testMethod void testocc(){
    
    	// GET USER FROM USER TABLE...
    	User u = [select name, Id  FROM user LIMIT 1];
    	
    	// RUN AS USER...
    	system.runAs(u)
	    {
	    	
		    // TEST ADDING A NEW ACCOUNT...                        
		    Account acc = new Account(
		    	name = 'temp validation account', 
		    	Owner_Division__c = 'test division'	
		    	);
	        insert acc; 
	        system.debug('----->>> END ADDING ACCOUNT: ' + acc.name);
	        
	        
	        // READ ACCOUNT...
	    	Account a = [select name, Id  FROM account WHERE name = 'temp validation account'];
	        system.debug('----->>> END READING ACCOUNT: ' + a.name);
	 	
	    	// TEST ADDING A NEW CONTACT...
	        Contact con = new Contact(
	        	AccountId = acc.id,lastname = 'testdata', 
	        	firstname ='testdata1',
	        	OwnerId = Userinfo.getUserid(),
	        	Owner_name_txt__c = 'textdata',
	        	Owner_region__c = 'testregion'
	        	);
	        insert con;  
	        system.debug('----->>> END INSERT CONTACT: ' + acc.name);
	    }
	    system.debug('----->>> RUNNING AS USER: ' + u.name);

   }        
        
}

 

 

I was playing around with above in the Eclipse tool. But im new to it all and dont even understand how to verify if something actually happens. I dont get an error message but the average test score is not changed whatever i do. 

 

Can someone please help me with the basics. Thanks...

Mattias NordinMattias Nordin

Anyone care to explain to a beginner how this works?
I want to learn...

Reppin__505Reppin__505

I'm new to the test classes as well. Here are some things i learned along the way:

-Remember when creaing an instance of a record to add both the required fields (otherwise a Null Exception will happen) and the fields that your trigger will be expecting.

-If you get a DML exception, the debug log will point you to the area in the trigger which has caused the exception.

-Bulkify the test script by creating and inserting 200 records.

-Make sure there are no SOQL queries or DML Statements such as 'Update' inside of loops within the trigger.

-Use collections such as (Sets, Maps, and Lists).

-Any object that you query in your trigger, create an instance of that object in your test script.

 

 

 

 

I have a question if anyone out there is listening. Should there be a special test class if you have a 'Delete' trigger? Are there any special testing methods that would apply to a Delete trigger other than creating record instances and then deleting them?

Thanks.

sfdcfoxsfdcfox

The ultimate point of a test method is to ensure that your logic is free of "logic errors". Syntax errors will prevent your code from compiling on the platform, so these are the ones you notice first. However, often times you will introduce "logic errors", a class of error that will only present itself in certain scenarios. For example, I once wrote a game of Yahtzee! for a friend as an exercise to expand my knowledge of C++, and after I resolved all of my syntax errors, I let my friend play the game. She noted that a Yahtzee! of six (that is, five sixes appear on the dice), she would score no points instead of the 50 or 100 that she should have. The other faces (one through five) scored normally. This is a type of error that one might only find after carefully reviewing the code or, as is more frequently the case, by testing the code.

 

When you write a test method, it should have a liberal number of System.Assert and System.AssertEquals methods. If your code sends an email when records are deleted, make sure the email is sent. If a related record's data is updated, query the related record and make sure. You can freely delete, insert, update, etc records as you need to during a test, and they will never have any lasting impact on the server. The last thing that you want to do is release a product that, weeks later, is found to have a crippling bug, causing many man-hours of debugging, having to notify your clients about the errors, possibly creating new packages for installation, data migration headaches, etc.

 

And while it's true that you could manually test the code for errors, it is just as likely that, at some point, you will need to have automated testing in place to reduce the amount of testing you need to do manually. As you continue to modify code, a change in one location could have adverse affects on a seemingly unrelated section; without automatic testing, you have no easy way to verify where the problem is.

 

And, of course, ultimately, remember that every trigger must be tested, even if it is only a delete trigger. Any triggers with 0% coverage during tests will not deploy, and if they are not tested completely, might prevent other packages from deploying later. You should aim to test for 100% coverage, while checking for logic errors, but if 100% proves impossible for some reason (pretty much, callouts are the only reason these days), you should at least be able to achieve coverage in the high 90+ range. As much as feasible, test as many conditions as practical, including branches that should "never" happen (and if they should never happen, maybe they do not belong in your code, anyways).