[英]Thrown Exception not caught in UnitTest try/catch
I'm designing some code right now where I'm throwing an exception if a string parameter is null or empty and the exception is thrown as it should be, but it isn't getting caught when I'm UnitTesting. 我现在正在设计一些代码,如果字符串参数为null或为空,我抛出一个异常,并且应该抛出异常,但是当我进行UnitTesting时它不会被捕获。
Here's the client I'm using. 这是我正在使用的客户端。
public class PipeClient : IPipeClient
{
public async void Send(string host, string pipeName, Message msg)
{
if (string.IsNullOrEmpty(msg.PreparedMessage))
throw new ArgumentException("MESSAGE_NOT_FOUND");
if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(pipeName))
throw new ArgumentNullException();
if (!host.TryParseHost())
throw new ArgumentException("INVALID_HOST_NAME");
using (var pipeClient = new NamedPipeClientStream(host, pipeName, PipeDirection.Out))
{
pipeClient.Connect(200);
using (var writer = new StreamWriter(pipeClient))
{
await Task.Run(() => writer.WriteLine(msg.PreparedMessage));
writer.Flush();
}
}
}
}
And here's the UnitTest 这是UnitTest
[TestMethod]
public void Send_FailsOnWrongHostName()
{
var name = "FailWithHostname";
var msg = new Message(MyStates.Register, "UnitTest", "Test");
try
{
var client = new PipeClient();
client.Send("lol", name, msg);
}
catch (Exception e)
{
Assert.IsTrue(e is ArgumentException);
}
}
So when I run that test it should as far as I know throw the exception when I call the the Send method (which is does) and then get caught in the catch clause because I'm not catching it inside the PipeClient. 因此,当我运行该测试时,就我所知,当我调用Send方法时抛出异常(这样做)然后被catch子句捕获,因为我没有在PipeClient中捕获它。 Yet it doesn't, it just exits with a failed test.
然而事实并非如此,只是在测试失败的情况下退出。
If you need any more information just let me know, thanks in advance. 如果您需要更多信息,请提前告知我们。
there's a few things I want to raise in this answer. 我想在这个答案中提出一些事情。 I'm not sure of your experience level so please don't think I'm being condescending at any point.
我不确定你的经验水平,所以请不要认为我在任何时候都是居高临下。
Firstly a brief note on async methods and Tasks. 首先是关于异步方法和任务的简要说明。
"In observed Tasks no one can you scream" -Me ,2018
“在观察到的任务中,没有人可以尖叫”-Me,2018年
Now if none of this is making much sense to you, I would recommend doing some reading up Tasks and async/await. 现在,如果这对你没有多大意义,我建议你做一些阅读任务和异步/等待。
Now onto your Test. 现在进入你的测试。
Your method is async void so there is nothing for the calling method to have returned to it to represent the work or to let it know that the method has thrown an exception. 您的方法是异步void,因此调用方法没有任何内容可以返回它来表示工作或让它知道该方法引发了异常。 So it carries on, the test finishes and then everything completes with no exceptions because the UnobservedTaskException can be thrown at anypoint in the future (I think it is related to when the garbage collector tidies up the faulted Task and then it throws and because the garbage collector is non-deterministic we can't say when that will happen)
所以它继续,测试完成,然后一切都没有异常完成,因为UnobservedTaskException可以在未来的任何一点被抛出(我认为这与垃圾收集器整理故障的任务然后它抛出并因为垃圾有关收藏家是非确定性的,我们不能说什么时候会发生)
So what if you made your async method return a Task??? 那么如果你让你的异步方法返回一个任务怎么办? Well that's still not quite right.
那还不太对劲。 You are now returning a Task that will be in a faulted state because of the exception, however because you never await it, the exception is never 'unwrapped' and actually thrown and so you're test happily continues.
您现在正在返回一个因异常而处于故障状态的任务,但是因为您永远不会等待它,该异常永远不会被“解包”并且实际上被抛出,因此您将继续愉快地进行测试。
What you need to do is make your Test async and return a Task and make the method you're testing async Task not async void and await that method in your test. 你需要做的是让你的测试异步并返回一个任务并使你正在测试异步的方法任务不是async void并等待测试中的那个方法。
Like this 像这样
[TestMethod]
public async Task Send_FailsOnWrongHostName()
{
var name = "FailWithHostname";
var msg = new Message(MyStates.Register, "UnitTest", "Test");
try
{
var client = new PipeClient();
await client.Send("lol", name, msg);
}
catch (Exception e)
{
Assert.IsTrue(e is ArgumentException);
}
}
public class PipeClient : IPipeClient
{
public async Task Send(string host, string pipeName, Message msg)
{
if (string.IsNullOrEmpty(msg.PreparedMessage))
throw new ArgumentException("MESSAGE_NOT_FOUND");
if (string.IsNullOrEmpty(host) || string.IsNullOrEmpty(pipeName))
throw new ArgumentNullException();
if (!host.TryParseHost())
throw new ArgumentException("INVALID_HOST_NAME");
using (var pipeClient = new NamedPipeClientStream(host, pipeName, PipeDirection.Out))
{
pipeClient.Connect(200);
using (var writer = new StreamWriter(pipeClient))
{
await Task.Run(() => writer.WriteLine(msg.PreparedMessage));
writer.Flush();
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.