Question

Ok, I have an Nunit test class setup that runs though a method, lets all it CalcBalance(). Within CalcBalance() we have another method that will save things to a database. I do not want to deal with the database when testing this particular method, but when I run my tests the database method throws an exception and causes the test to fail because the databases isn't setup/mocked. Example:

CalcBalance()
{

//Stuff I want to test

DatabaseInteraction()     //Throws exception

 return;         //This is the value I want to have tested.

}

My question is, is there any way I can set this up so that the Nunit tester will continue to test through even though the database interaction is saying it failed. I commented out DatabaseInteraction() and ran the test and it went through fine.

Was it helpful?

Solution

The functionality inside DatabaseInteraction which is causing the exception should be abstracted out to another class which implements an interface. This interface can then be mocked for use in unit testing.

For example:

public class BalanceCalculator
{
    readonly IDatabaseInteraction _databaseInteraction;

    public BalanceCalculator(IDatabaseInteraction databaseInteraction)
    {
        _databaseInteraction = databaseInteraction;
    }

    public Decimal CalcBalance()
    {
        //Stuff I want to test

        _databaseInteraction.Interaction();

        return 5.0D;         //This is the value I want to have tested.
    }
}

Then in the unit test, it can be done like this (using Moq):

[Test]
public void CheckValueTest()
{
    Mock<IDatabaseInteraction> mockInteraction = Mock<IDatabaseInteraction>();
    BalanceCalculator balanceCalculator = new BalanceCalculator(mockInteraction.Object);

    decimal result = balanceCalculator.CalcBalance();
    Assert.AreEqual(5.0D, result);
}

The IDatabaseInteraction is mocked to do nothing, so there is no chance of an exception or any unrelated functionality taking place.

For further information, read up on Inversion of Control, it is really useful for testability.

OTHER TIPS

Sounds to me like you need to split up your code so each function/class has its own responsibility. After you split it up you can test each part separately.

I would have to agree with @Sebastiaan Megens here. The 'correct' way to achieve this would be to

a) Have your database interaction loosely coupled using an interface and then simply create a mock DB in testing code or

b) Design your code so that each object can function as a standalone entity.

That being said, I believe you can configure your test to expect an exception of a certain type, meaning it wont fail if such an exception is thrown during execution. Far from ideal but, this is the price you pay for tightly-coupled architectures. On a similar line of thinking, in your test simply wrap the code which calls MyObject.CalcBalance in a try...catch and proceed as normal.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top