2

I wrote a trigger to prevent more than n incidents for a client(lookup to user) at any point of time.

  trigger CountLimit on Incident__c (after insert,after update,after undelete) {
  Set<Id> clientids = new Set<Id>();
    Map<Id,Integer> clientmap = new Map<Id,Integer>();
    Max_Incidents__c cs = Max_Incidents__c.getInstance('Platinum');
    Integer maxincs = (Integer)cs.MaxIncidentsPerClient__c;

    for(Incident__c inc:Trigger.new)
    {
        clientids.add(inc.Client__c);
    }

    Map<Id,User> usermap = new Map<Id,User>([select id,name from user where id in:clientids]);

    for(AggregateResult result:[select count(id) sum, client__c client from Incident__c where client__C in:clientids group by client__C])
    {
        clientmap.put((Id)result.get('client'),(Integer)result.get('sum'));
    }

    for(Incident__c inc:Trigger.new)
    {
        if(clientmap.get(inc.Client__c)>maxincs)
        {
           inc.addError('You can\'t open more than '+maxincs+' incidents for '+ usermap.get(inc.Client__c));
        }
    } 

And I wrote this test class-

@isTest
public class IncidentLimit_Test {
    public static testmethod void testcountincident(){

        User usr = CreateUser('Ben','Bentaleb');
          List<Incident__c> inclist = new List<Incident__c>();  
        try{
        System.runAs(usr){
            Test.startTest();
            for(integer i=1;i<=5;i++)
            {
              inclist.add(new Incident__c(client__c=usr.id,Description__c='incident'+i));
            }
           insert inclist;
        Test.stopTest();
        }
       }

    catch(exception e){
      e.getmessage().contains('You can\'t open more than');
      }
        finally{
             System.assertEquals(5, inclist.size());}
               }

public static UserRole CreateUserRole(String name) {
    UserRole ur = new UserRole();
    ur.Name = name;
   insert ur;
    return ur;
}

    public static User CreateUser(String firstname, String lastname) {
    UserRole ur = CreateUserRole('Testing');
         profile pr = [SELECT Id FROM Profile WHERE Name='Standard User'];
    User usr = new User(FirstName = firstname,
                        LastName = lastname,
                        Username = firstname + '.' + lastname +      '@testing.com',
                        IsActive = true,
                        UserRoleId = ur.Id,
                        Email = '[email protected]', 
                        Alias = 'tusr', 
                        TimeZoneSidKey = 'Europe/Berlin' , 
                        LocaleSidKey = 'en_US', 
                        EmailEncodingKey = 'UTF-8', 
                        ProfileId = pr.id, 
                        LanguageLocaleKey = 'en_US'
                        );
        insert usr;
    return usr;
  }
}

The issue I'm here facing is until I add the parameter (seealldata=true) into the annotation the code coverage remains 26% otherwise it's 93%. Please advise.

7
  • 1
    I wouldn't of expected your code coverage to vary based on the seealldata annotation. Your test is creating a user and setting the Client__c to that new user so your trigger should be ignoring all the Incident__c records in your org because of this.
    – BarCotter
    Mar 6, 2015 at 13:12
  • FYI: The reason you are only getting 26% with seealldata set to false is because your trigger is running on before insert which means the Incident__c records have not been inserted into the database so your SOQL query returns no results.
    – BarCotter
    Mar 6, 2015 at 13:16
  • @BarCotter sorry I pasted the wrong code, but the events are (after insert,after update,after undelete) and the result is the same. Can you please think of any other reason?
    – Jarvis
    Mar 6, 2015 at 13:51
  • 1
    Just an FYI. Just like custom objects you have to create data for Custom settings as well. Unless you add seeAllData=true you cannot access the custom setting. So try creating the custom setting data in test class, remove the seeAllData and check for coverage.
    – Sam
    Mar 6, 2015 at 14:02
  • 1
    Max_Incidents__c.MaxIncidentsPerClient__c may not be set when using seeAllData=false, when it's true you will be using whatever value is set in your org. You test should be creating this custom settting.
    – BarCotter
    Mar 6, 2015 at 14:13

2 Answers 2

4

Max_Incidents__c.MaxIncidentsPerClient__c will not be set when using seeAllData=false, when it's true you will be using whatever value is set in your org.

Your test should be creating that custom setting as well.

3
  • Another learning I got is custom settings are setup objects. So we have to avoid Mixed DML error.
    – Jarvis
    Mar 6, 2015 at 14:58
  • Custom Settings are not setup objects. Its the User record that is the setup object in your code. See here for a list of setup objects.
    – BarCotter
    Mar 6, 2015 at 15:08
  • Yes, for few minutes my understanding got broke.
    – Jarvis
    Mar 6, 2015 at 15:20
3

In your trigger not all of the code will execute every time. You have if-statements and for-loops. Which lines of your code are executed depend actually much on the specific data you are processing.

With seealldata=false the tests act on a subset of data, usually test-data you create programmatically just for the test.

However if you use seealldata=true, the test can operate over the content of you entire database. Because greater variety of records, more lines will be executed in the trigger and your codecoverage is higher. At the same time seealldata=true comes with serious tradeoffs, since test-results are depending on variable data, you might loose portability and huge data volume can cause severe performance issues. One example I had a couple of years ago was that code deployment form Sandbox to Production took longer and longer. It started with about 30 seconds and soon reached > 10 minutes. Reason was test-execution with seealldata=true. And 10 minutes is just the start: deployments might cost hours after your amount of data has grown big.

To improve the situation without using seealldata=true, you need to create better test data so that more lines of your code will be executed. You can use Developer Console to highlight the uncovered lines of code and adjust or extend you test data accordingly.

Unfortunately there is some data you can't create, like the Standard Pricebook. To get related code covered, seealldata might by the only option in some scenarios.

As best practice you should avoid seealldata=true when possible and use it only in rare cases where really required. At the same time you should try to generate a wide range of test-data programmatically to ensure good coverage.

See also:

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .