0

I have a trigger on a custom Student object that is suppose to assign the lookup field Advisor based off of another look up field Gender. Basically my trigger goes:

...
if (newStudent.Gender__c == null) {
    newStudent.addError('\'Gender\' missing');
    return;
}

And my test goes:

Student__c newStudent = new Student__c();
// Skip assigning gender
insert newStudent;

I am able to get 100% code coverage for my trigger, but the test technically fails. If I assign the gender, I get a passed test but I don't get 100% code coverage.

How are you suppose to get 100% test coverage on a trigger that applies its own validation on a field?

2
  • Correct me if I'm misunderstanding the issue. I would expect your tests to insert / create at least two Student__c records, one with a gender specified and one without to cover these two data scenarios. Is there more complication to the test scenario here?
    – Mark Pond
    Feb 4, 2019 at 23:09
  • That's exactly what is suppose to happen but the test gets marked as failed because the insert without a gender fails...
    – BlondeSwan
    Feb 4, 2019 at 23:12

2 Answers 2

1

You'll need to wrap your insert statement in a try/catch block to trap the exception that ensues, and, critically, write assertions to validate that you really did catch an exception and it was the exception you expected - i.e., your code didn't throw an exception you weren't looking for!

Here's what that might look like here (there is more than one way to do this, but this is how I do it in my tests):

Student__c newStudent = new Student__c();
// Skip assigning gender
Boolean caught = false;

try {
   insert newStudent;
} catch (DMLException e) {
    System.assert(e.getMessage().contains('Gender'), 'correct exception caught');
    caught = true;
}
System.assertEquals(true, caught, 'caught the expected exception');

The two assertions ensure that

  • You did catch an exception.
  • The exception you caught was the correct one that your code was supposed to throw.
  • You get a meaningful assert failure if either condition isn't as designed.

This is a failure-case test, and should be tested in a separate unit test from your positive test cases.

0

One thing to point out is that the second parameter in the assertion is the error text when the assertion fails. It is not a success message.

Additionally, an assertion needs to be added after the line which is expected to fail. Reaching that deliberately failing assertion means in this case that the error text wasn't added to the record because of the missing gender.

Using David's test code as a good starting point:

Student__c newStudent = new Student__c();

try {
   insert newStudent; // this will error, since .addError() was used elsewhere

   // an assertion needs to be made after the operation which should fail
   // without it, a scenario which should have failed may silently succeed and you would not know it

   system.assert(false, 'An error should have been added to the record.'); 

} catch (DMLException e) {
    // this is a failure message output, not success text
    System.assert(e.getMessage().contains('Gender'), 'Expected a gender message in the exception.'); 
}

You must log in to answer this question.

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