views:

139

answers:

4

I'm unit testing a demo application, which is a POP3 client. The POP3 client implements IDisposable, so I'm trying to test a 'using' cycle.

(I'm using nunit 2.5.2 and Moq 4.0)

    /// <summary>
    /// Unsuccesfull construct dispose cycle, no ILogger object given. 
    /// Expecting ArgumentNullException. Expecting TcpClient dispose to be called.
    /// </summary>
    [Test]
    [ExpectedException(typeof(ArgumentNullException))]
    public void ConstructorDispose_LoggerNull_ArgumentNullException()
    {
        mockTcpClient.Setup(x => x.Dispose());

        using (var popClient = new PopClient(null, mockTcpClient.Object))
        {

        }

        mockTcpClient.VerifyAll();
    }

As you can see the verifyAll method will never be invoked and the test will be succefull, non the less. What is the best way to solve this? Is there another way then try catch?

Update I fixed it like this for the moment:

        mockTcpClient.Setup(x => x.Dispose());

        var correctExceptionThrown = false;

        try
        {
            using (var popClient = new PopClient(null, mockTcpClient.Object))
            {

            }
        }
        catch (ArgumentNullException)
        {
            correctExceptionThrown = true;
        }
        finally
        {
            mockTcpClient.VerifyAll();
        }

        Assert.That(correctExceptionThrown);

But dispose isn't called, seems to be the c# specification.

+1  A: 

You seem to be testing that the injected mockTcpClient instance is disposed even if the constructor throws an exception, in which case this should work:

mockTcpClient.Setup(x => x.Dispose());
try
{
    var popClient= new PopClient(null, mockTcpClient.Object);
}
finally
{
    mockTcpClient.VerifyAll();
}

EDIT: Actually, try/finally would be cleaner than catching Exception. Note that you don't need to dispose popClient since no instance is created.

Lee
+2  A: 
mockTcpClient.Setup(x => x.Dispose());

try 
{
    using (var popClient = new PopClient(null, mockTcpClient.Object))
    {

    }
}
finally 
{
    mockTcpClient.VerifyAll();
}
Nat
You got to verify that It's throwing the right exception.
JJoos
+1  A: 

You have already discovered that dispose really is not supposed to be called if the constructor fails. But there may still be other cases where you might want to to verify your mocks after an expected exception is thrown. I just do that in the test TearDown like this:

[SetUp]
public void SetUp()
{
   this.mockFactory = new MockFactory(MockBehavior.Loose);
}

[TearDown]
public void TearDown()
{
   this.mockFactory.VerifyAll();
}


[Test]
[ExpectedException(typeof(NoBananasException))]
public void EatThrowsIfNoBananasAvailable
{
   var bananaProvider = this.mockFactory.Create<IBananaProvider>();
   bananaProvider.SetUp(bp => bp.IsBananaAvailable).Returns(false).Verifiable();

   var monkey = new Monkey(bananaProvider.Object);
   monkey.Eat();
}
Wim Coenen
+1  A: 

This doesn't answer your question (as it's already solved), but it's relevant and worth posting anyway.

[ExpectedException] is a pretty ropey way to test exceptions. It can be error prone, as the wrong line can trigger an exception of the expected type resulting in an erroneous pass. I would strongly advocate that you check out Assert.Throws() instead :)

It's nicer to use (you can query the returned exception), more readable and, above all, safer.

You can find an example here

Mark Simpson