C#中的异步任务的NUnit测试失败

时间:2016-12-20 15:58:55

标签: c# nunit task-parallel-library task moq

我有以下类和接口

public interface IService
{
    Task<double> GetAccDetails(int personId);
}

public class Person
{
    private int _personId;
    private IService _service;

    public Person(int personId, IService service)
    {
        _personId= personId;
        _service = service;
    }

    public double Amount {get; set;}

    public async void UpdateBanckingAcc()
    {
        Amount = await _service.GetAccDetails(_personId);
    }
}

我正在尝试为它编写nunit测试:

[Test]
public async void Test1([Values(200)]int personId)
{
    const double expectedResult = 20;    
    var serviceMock = new Mock<IAccountService>();

    //Here I tried both options:
    //serviceMock.Setup(s =>  s.GetAccDetails(It.Is<int>(id => id == personId)))
    //    .ReturnsAsync(() => expectedResult);
    //And:
    serviceMock.Setup(s=>  s.GetAccDetails(It.Is<int>(id => id == personId)))
    .Returns(() => Task.FromResult<double>(personId));

    var person = new Person(personId, serviceMock.Object);

    person.UpdateBanckingAcc();

    double res = person.Amount;
    Assert.AreEqual(expectedResult, res);
}

测试失败。由于一些奇怪的原因,我无法调试它 所以我在这里看到的问题是电话:

person.UpdateBanckingAcc();

应该是

await person.UpdateBanckingAcc();

但如果我使用await关键字,则不喜欢。

请告知。

还有一个问题:对于我应该测试的异步方法的nunit测试,有什么特定的东西,比如任务状态测试等吗?

2 个答案:

答案 0 :(得分:0)

此处的问题是,您的方法UpdateBankingAcc的返回类型void应该返回Task<T>Task,因此您需要将其签名更改为重新命名Task,如:

public async Task UpdateBanckingAcc()
{
    Amount = await _service.GetAccDetails(_personId);
}

现在您需要将测试代码更改为:

await person.UpdateBanckingAcc();

double res = person.Amount;
Assert.AreEqual(expectedResult, res);

你永远不应该从异步方法返回void,除非它是UI控件事件,你可以阅读有关使用async的最佳实践并等待以下内容:

https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

http://www.tonicodes.net/blog/why-you-should-almost-never-write-void-asynchronous-methods/

async/await - when to return a Task vs void?

答案 1 :(得分:0)

有一条简单的规则:async void用于即发即弃行为,仅用于此目的。如果您需要async方法,请将其返回类型更改为Task,如@EhsanSajjad所述。这也与单元测试相对应:

public async Task UpdateBanckingAcc()

public async Task Test1([Values(200)]int personId)