petko_stankoski
petko_stankoski

Reputation: 10713

Unit tests for handled exceptions

This is what I have in code:

function myMethod()
{
    foreach(var file in files)
    {
        if (noMatch)
        {
            //
            SendEmailAndStopProcessing();
            continue;
        }
        doSomething();
    }
}

I have a csv file which has multiple lines and I process them if there is a match with a db value.

I want to create a unit test that confirms that if noMatch is found, then the email will be sent and doSomething wont be executed. I don't have an exception here because there is no need of that, it is handled by sending email (those were the business rules). However I need to create a unit test to confirm that this case is handled. How should I handle that? If there was an exception I would have added the attribute for expected exception in my test method, but since there is not, I am stuck.

Upvotes: 0

Views: 82

Answers (2)

Callum Bradbury
Callum Bradbury

Reputation: 956

Whatever functionality is sending the email within SendEmailAndStopProcessing() should be pulled out into an interface (IEmailSender or something), allowing you to inject that interface in through the constructor of your class.

Once you have this, you can use Moq or some other mocking framework, to replace the IEmailSender implementation with a stub which won't actually send an email. With these you can usually do assertions on how many times a method was called, if at all, so if you were using Moq (for example), you could do.

emailMock.Verify(x => x.SendEmail(), Times.Once)

Which would fail if your SendEmail wasn't called. You could do something similar for your OrSomething method, also.

The key is isolating components into interfaces, so that they can be swapped out at will, using the Liskov Substitution Principle.

Upvotes: 1

Georg Patscheider
Georg Patscheider

Reputation: 9463

As Kritner has said: create a mock of SendEmailAndStopProcessing and count how often it has been called. This of course assumes that SendEmailAndStopProcessing can be mocked (method is accessible from test class and can be overridden).

For example using Moq:

using Moq;

// ARRANGE
var serviceMock = new Mock<MyService>();
serviceMock.Setup(s => s.SendEmailAndStopProcessing()).Verifiable();
// ACT: call myMethod()
// ASSERT
const int expectedNumberOfCalls = 1;
serviceMock.Verify(x => x.SendEmailAndStopProcessing(), Times.Exactly(expectedNumberOfCalls));

Upvotes: 0

Related Questions