2014-07-18 21 views
5

Jestem zaskoczony moją przerwania po await ing to async metodę, która jest na linii, która odwołuje się do oczekiwanego Task<T> nigdy nie jest trafiony:Jak używać punktu przerwania po oczekiwaniu na test jednostkowy?

[Test] 
    public async void GetSomethingTest() 
    { 
     var service = SimpleIoc.Default.GetInstance<IService>(); 
     var result = await service.TryGetSomethingAsync(20); 
     Assert.IsTrue(result.IsSuccess); 
     Assert.IsNotNull(result.ReturnValue); 
    } 

Umieszczenie przerwania na pierwszym Assert linii nigdy nie jest trafiony, ale testy przechodzi.

Jak przerwać oczekiwanie na zwrot?

UPDATE: Myślę, że to dlatego, że ramy test nie jest await ing wywołanie metody testowej, Używam NUnit 2.6.3 i który twierdzi async wsparcia, jednak czy pociąga za sobą zerwanie po await Jakbym próbuję zrobić, nie jestem pewien ...

+1

Zmień metodę testową z async void na async Zadanie – Neel

+0

@Neel, które nie pomogło :( – markmnl

+1

Miałem wszelkiego rodzaju problemy z debugowaniem testów jednostkowych.Jeśli to nie działa tak, jak chciałeś, skopiuj swój test do ConsoleApplication i tam je debugować.To o wiele mniej kłopotów – nvoigt

Odpowiedz

10

Problem polega na tym, że twoja metoda to async void. To ma semantykę ognia i zapomnienia.

Konceptualnie co metoda robi z async - Zastosowanie await wygląda następująco:

[Test] 
public void GetSomethingTest() 
{ 
    var service = SimpleIoc.Default.GetInstance<IService>(); 
    service.TryGetSomethingAsync(20).ContinueWith(t => 
    { 
     var result = t.Result; 
     Assert.IsTrue(result.IsSuccess); 
     Assert.IsNotNull(result.ReturnValue); 
    }); 
} 

Teraz powinno być jasne, na czym polega problem. Twoja metoda testowa natychmiast powraca, gdy tylko TryGetSomethingAsync zwróci swoją Task. Tak więc test natychmiast się kończy. Ponieważ nie zgłoszono żadnych wyjątków, jest to sukces.

Jeśli system testowania obsługuje Task testy -returning, można naprawić swój test, aby robić to, co chcesz, po prostu zmieniając typ zwracany do Task zamiast void.

[Test] 
public async Task GetSomethingTest() 
{ 
    var service = SimpleIoc.Default.GetInstance<IService>(); 
    var result = await service.TryGetSomethingAsync(20); 
    Assert.IsTrue(result.IsSuccess); 
    Assert.IsNotNull(result.ReturnValue); 
} 

To będzie konceptualnie tłumaczyć na następujące.

[Test] 
public Task GetSomethingTest() 
{ 
    var service = SimpleIoc.Default.GetInstance<IService>(); 
    return service.TryGetSomethingAsync(20).ContinueWith(t => 
    { 
     var result = t.Result; 
     Assert.IsTrue(result.IsSuccess); 
     Assert.IsNotNull(result.ReturnValue); 
    }); 
} 

Wskazówki jak Task kontynuacją jest zwracany, tak że ramy test może teraz czekać na nią, zapewniając, że cały kod testu zawiera czas, aby uruchomić przed test jest uważany za zakończony.

(Technicznie ramy mogą być wykonane do pracy w przypadku async void jak dobrze, ale nie wiem, z jakiegokolwiek powodu, dlaczego to byłaby dobra cecha, więc spodziewam się najbardziej nie poradzić.)

Jeśli struktura testowa nie obsługuje testów zwracania zadań,, możesz naprawić test, używając .Result zamiast await.

[Test] 
public void GetSomethingTest() 
{ 
    var service = SimpleIoc.Default.GetInstance<IService>(); 
    var result = service.TryGetSomethingAsync(20).Result; 
    Assert.IsTrue(result.IsSuccess); 
    Assert.IsNotNull(result.ReturnValue); 
} 

to po prostu blokować bieżącego wątku aż Task zwrócony przez TryGetSomethingAsync jest zakończona.

+0

Przejście do MSTest i zwrócenie 'Task' rozwiązało mój problem, ale dzięki szczegółowej odpowiedzi, jestem pewien, że pomoże to innym! – markmnl