2016-12-20 22 views
2

У меня есть следующий класс и интерфейсNUnit тестирования асинхронной задачи не в C#

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 для методов async, которые я должен тестировать, например, тестирование состояния задачи и т. Д.?

+0

Какую версию NUnit вы используете? В последних версиях должно указываться, что асинхронный тест недействителен. – Charlie

ответ

0

Проблема здесь состоит в том, что ваш метод UpdateBankingAcc имеет тип возвращаемого void, который должен быть возвращающую Task<T> или Task, так что вам нужно изменить подписи ней reutrn Task как:

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

и теперь вы необходимо будет изменить тестовый код, чтобы быть:

await person.UpdateBanckingAcc(); 

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

вы никогда не должны возвращать пустоту от метода асинхронного, если оно не контролирует события UI, вы можете прочитать о быть й практика использования асинхр и ждет в следующем:

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?

+0

См. Мой последний комментарий –

+0

Способ, которым вы предложили внести изменения - неудачи. –

0

Существует простое правило: async void используется для огня и забыть поведения и только для это. Если вам нужен метод async, измените его тип возврата на Task, как сказал @EhsanSajjad. Это также соответствует единичным испытаниям:

public async Task UpdateBanckingAcc() 

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