无论如何,期望在测试中出现异常但想要验证dispose

时间:2009-10-24 12:53:39

标签: c# unit-testing nunit moq

我正在测试一个演示应用程序,它是一个POP3客户端。 POP3客户端实现IDisposable,因此我尝试测试using周期。

(我正在使用nunit 2.5.2和Moq 4.0)

/// <summary>
/// Unsuccessful 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();
}

正如您所看到的,verifyAll方法永远不会被调用,测试也会成功。所以...

  • 解决此问题的最佳方法是什么?
  • 还有另一种尝试捕捉吗?

更新我暂时解决了这个问题:

        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);

但是不称为dispose ,似乎是C#规范。

4 个答案:

答案 0 :(得分:3)

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

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

    }
}
finally 
{
    mockTcpClient.VerifyAll();
}

答案 1 :(得分:2)

如果构造函数失败,您已经发现dispose确实是而不是。但是在可能仍有其他情况下,您可能希望在抛出预期的异常后验证您的模拟。我只是在测试TearDown中这样做:

[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();
}

答案 2 :(得分:2)

这不能回答你的问题(因为它已经解决了),但无论如何它都是相关且值得发布的。

[ExpectedException]是测试异常的一种非常简单的方法。它可能容易出错,因为错误的行可能会触发预期类型的​​异常,从而导致错误传递。我强烈建议您查看Assert.Throws()而不是:)

使用起来更好(可以查询返回的异常),更具可读性,最重要的是更安全。

You can find an example here

答案 3 :(得分:1)

您似乎正在测试注入的mockTcpClient实例是否已处理,即使构造函数抛出异常,在这种情况下这应该有效:

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

编辑:实际上,try / finally比捕获Exception更清晰。请注意,您不需要配置popClient,因为没有创建实例。