NUnit3: Assert.Throws with async Task
本文关键字:async Task with Throws Assert NUnit3 | 更新日期: 2023-09-27 18:30:58
我正在尝试将测试移植到 NUnit3 并得到一个 System.ArgumentException : 不支持"异步无效"方法,请使用"异步任务"代替。
[Test]
public void InvalidUsername()
{
...
var exception = Assert.Throws<HttpResponseException>(async () => await client.LoginAsync("notarealuser@example.com", testpassword));
exception.HttpResponseMessage.StatusCode.ShouldEqual(HttpStatusCode.BadRequest); // according to http://tools.ietf.org/html/rfc6749#section-5.2
...
}
Assert.Throws 似乎采用 TestDelegate,定义为:
public delegate void TestDelegate();
因此,参数异常。移植此代码的最佳方法是什么?
这是由Nunit解决的。 您现在可以使用 Assert.ThrowsAsync<>()
https://github.com/nunit/nunit/issues/1190
例:
Assert.ThrowsAsync<Exception>(() => YourAsyncMethod());
我建议使用以下代码而不是Assert.ThrowsAsync
,因为这更具可读性:
// Option A
[Test]
public void YourAsyncMethod_Throws_YourException_A()
{
// Act
AsyncTestDelegate act = () => YourAsyncMethod();
// Assert
Assert.That(act, Throws.TypeOf<YourException>());
}
// Option B (local function)
[Test]
public void YourAsyncMethod_Throws_YourException_B()
{
// Act
Task Act() => YourAsyncMethod();
// Assert
Assert.That(Act, Throws.TypeOf<YourException>());
}
我最终编写了一个静态函数来镜像 NUnit 的功能。https://github.com/nunit/nunit/issues/464 对此进行了一整场对话。
public static async Task<T> Throws<T>(Func<Task> code) where T : Exception
{
var actual = default(T);
try
{
await code();
Assert.Fail($"Expected exception of type: {typeof (T)}");
}
catch (T rex)
{
actual = rex;
}
catch (Exception ex)
{
Assert.Fail($"Expected exception of type: {typeof(T)} but was {ex.GetType()} instead");
}
return actual;
}
然后从我的测试中我可以使用它,例如
var ex = await CustomAsserts.Throws<HttpResponseException>(async () => await client.DoThings());
Assert.IsTrue(ex.Response.StatusCode == HttpStatusCode.BadRequest);
为了确保抛出异常,如果您选择使用异常,最好不要在 catch 块中断言。这样,您可以确保抛出正确的异常类型,否则您将获得 null 引用或未捕获的不同异常。
HttpResponseException expectedException = null;
try
{
await client.LoginAsync("notarealuser@example.com", testpassword));
}
catch (HttpResponseException ex)
{
expectedException = ex;
}
Assert.AreEqual(HttpStatusCode.NoContent, expectedException.Response.BadRequest);
你可以尝试使用这样的东西:
try
{
await client.LoginAsync("notarealuser@example.com", testpassword);
}
catch (Exception ex)
{
Assert.That(ex, Is.InstanceOf(typeof (HttpResponseException)));
}