期望测试中出现异常,但无论如何都想验证调用了 dispose
我正在对一个演示应用程序进行单元测试,它是一个 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# 规范。
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>
/// 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();
}
As you can see the verifyAll
method will never be invoked and the test will be successful, nonetheless. So ...
- 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这并不能回答您的问题(因为它已经解决了),但它是相关的并且无论如何都值得发布。
[ExpectedException] 是一种非常可靠的测试异常的方法。它可能容易出错,因为错误的行可能会触发预期类型的异常,从而导致错误的传递。我强烈建议您改为查看 Assert.Throws() :)
它更好用(您可以查询返回的异常),更具可读性,最重要的是,更安全。
您可以在此处找到示例
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
您已经发现,如果构造函数失败,确实不应该调用 dispose。但在其他情况下,您可能希望在引发预期异常后验证您的模拟。我只是在测试 TearDown 中这样做:
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:
您似乎正在测试即使构造函数抛出异常,注入的mockTcpClient实例也会被释放,在这种情况下这应该有效:
编辑:实际上,try/finally会比捕获异常更干净。请注意,您不需要处置 popClient,因为没有创建实例。
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:
EDIT: Actually, try/finally would be cleaner than catching Exception. Note that you don't need to dispose popClient since no instance is created.