简体   繁体   English

NUnit3:Assert.Throws 与异步任务

[英]NUnit3: Assert.Throws with async Task

I am trying to port a test to NUnit3 and am getting a System.ArgumentException : 'async void' methods are not supported, please use 'async Task' instead.我正在尝试将测试移植到 NUnit3 并收到 System.ArgumentException :不支持“async void”方法,请改用“async Task”。

[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 appears to take a TestDelegate, defined as: Assert.Throws 似乎采用了 TestDelegate,定义为:

public delegate void TestDelegate();

hence the ArgumentException.因此是 ArgumentException。 What is the best way to port this code?移植此代码的最佳方法是什么?

This was resolved by Nunit.这已由 Nunit 解决。 You can now use Assert.ThrowsAsync<>()您现在可以使用 Assert.ThrowsAsync<>()

https://github.com/nunit/nunit/issues/1190 https://github.com/nunit/nunit/issues/1190

Example:例子:

Assert.ThrowsAsync<Exception>(() => YourAsyncMethod());

I would recommend the following code instead of Assert.ThrowsAsync , as this is more readable:我会推荐以下代码而不是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>());
}

To ensure the exception was thrown, it's better to not assert in the catch block if you so choose to use one.为了确保抛出异常,如果您选择使用一个,最好不要在 catch 块中断言。 This way, you can be sure the correct exception type is thrown because otherwise you'll get a null reference or an uncaught different exception.这样,您可以确保抛出正确的异常类型,否则您将获得空引用或未捕获的不同异常。

HttpResponseException expectedException = null;
try
{
    await  client.LoginAsync("notarealuser@example.com", testpassword));         
}
catch (HttpResponseException ex)
{
    expectedException = ex;
}

Assert.AreEqual(HttpStatusCode.NoContent, expectedException.Response.BadRequest);

I ended up writing a static function that mirrors what NUnit does.我最终编写了一个反映 NUnit 功能的静态函数。 There was a whole conversation at https://github.com/nunit/nunit/issues/464 about this.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;
}

Then from my tests I can use it such as然后从我的测试中我可以使用它,例如

var ex = await CustomAsserts.Throws<HttpResponseException>(async () => await client.DoThings());
Assert.IsTrue(ex.Response.StatusCode == HttpStatusCode.BadRequest);

You could try using something like this:你可以尝试使用这样的东西:

 try
 {
     await client.LoginAsync("notarealuser@example.com", testpassword);
 }
 catch (Exception ex)
 {
     Assert.That(ex, Is.InstanceOf(typeof (HttpResponseException)));
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM