Ta odpowiedź nie doda nic nowego do powyższych, ma jedynie na celu wyartykułowanie odpowiedzi w bardziej szczegółowy sposób, ponieważ zadziałało właśnie dla mnie. Kiedy pojawił się problem opisany w pytaniu powyżej, spędziłem wiele czasu próbując znaleźć sposób, aby upewnić się, że wszystkie obietnice miały czas na zakończenie i wszystkie twierdzenia zostały potwierdzone.
W moim przypadku miałem serię obietnic, a po każdym muszę upewnić się, że wyniki odpowiadają moim oczekiwaniom. Nie utworzyłem żadnej obietnicy przy użyciu deferred
, raczej powoływałem się na istniejące.
Chodzi o to, że $timeout.flush()
był dla mnie całkowicie wystarczający. Moja próba pracy wygląda następująco:
describe("Plain command without side-effects", function() {
it("All usecases", inject(function($timeout) {
console.log("All together");
expect(state.number).toEqual(1);
cmdHistory
.execute(increaseState, decreaseState)
.then(function() {
console.log("Execute works");
expect(state.number).toEqual(2);
return cmdHistory.redo(); // can't redo, nothing's undone
})
.then(function() {
console.log("Redo would not work");
expect(state.number).toEqual(2);
return cmdHistory.undo();
})
.then(function() {
console.log("Undo undoes");
expect(state.number).toEqual(1);
return cmdHistory.undo();
})
.then(function() {
console.log("Next undo does nothing");
expect(state.number).toEqual(1);
return cmdHistory.redo(); // but still able to redo
})
.then(function() {
console.log("And redo redoes neatly");
expect(state.number).toEqual(2);
});
$timeout.flush();
}));
Test ten przeznaczony jest, aby upewnić się, że commandHistory obiekt działa poprawnie, to musi działań: execute
i unExecute
i trzech metod: execute
, undo
, redo
, którego zwrot wszystkich obietnice.
Bez numeru $timeout.flush()
, wszystkie dane wyjściowe dziennika miały wartość All together
i nie zawierały dalszych komunikatów dziennika.Dodawanie $timeout.flush()
ustaliła wszystkiego, a teraz mam wszystkie komunikaty pokazane i wszystkie twierdzenia wykonany
UPDATE Jest jeszcze jedna opcja: można napisać swój zestaw testowy bez łączenia obietnic then
, ale po prostu płukania po każdym obietnica została nazywa, tak aby upewnić się, że kończy:
it("All usecases 2", inject(function($timeout) {
console.log("All usecases 2");
expect(state.number).toEqual(1);
console.log("Execute works");
cmdHistory.execute(increaseState, decreaseState);
$timeout.flush();
expect(state.number).toEqual(2);
console.log("Redo would not work");
cmdHistory.redo(); // can't redo, nothing's undone
$timeout.verifyNoPendingTasks();
expect(state.number).toEqual(2);
console.log("Undo undoes");
cmdHistory.undo();
$timeout.flush();
expect(state.number).toEqual(1);
console.log("Next undo does nothing");
cmdHistory.undo();
$timeout.verifyNoPendingTasks();
expect(state.number).toEqual(1);
console.log("And redo redoes neatly");
cmdHistory.redo(); // but still able to redo
$timeout.flush();
expect(state.number).toEqual(2);
}));
Proszę zwrócić uwagę na to, w niektórych przypadkach, gdy moje metody, takie jak undo
i redo
nie zwracają obietnicę, wzywam $timeout.verifyNoPendingTasks()
zamiast flush
. Trudno powiedzieć, czy to dobrze, czy źle.
Jednak w tym przypadku test wygląda bardziej sensownie i znacznie prościej.
Jeśli testowanie obiecuje, dlaczego w ogóle chcesz używać składni async, zarówno w starej, jak i nowej Jasmine? Czy możesz opublikować funkcję, którą próbujesz przetestować? W wielu przypadkach można użyć '$ timeout.flush()' i/lub 'myPromise.resolve()' w testach, aby wymusić synchronizację. –
@MichalCharemza Ku mojemu zaskoczeniu, '$ timeout.flush()' działa świetnie bez użycia 'done' Jasmine; Nie mam funkcji do zademonstrowania, kiedy potrzebuję 'done' +' $ timeout.flush() '. Co jeśli testy wykorzystują np. rzeczywisty backend '$ http'? To jest (oczywiście) lepiej kpić z '$ http' dla szybkości, ale czy' $ timeout.flush() 'bez' done' tam działa? Czy opóźnione rozwiązanie obietnicy robi jakąkolwiek różnicę? –
Jeśli testy używają rzeczywistego backendu '$ http', łączącego się z prawdziwym serwerem, wówczas test byłby asynchroniczny i trzeba użyć' done'. '$ timeout.flush()' (lub '$ httpBackend.flush()') wpływa na kod działający lokalnie: nie można wywołać funkcji, aby zażądać od serwera odpowiedzi na żądanie już teraz! Jeśli nie masz pewności, jak przetestować określoną funkcję (powiedzmy, używając '$ timeout' lub' $ http'), możesz umieścić tę funkcję w pytaniu). –