Как протестировать метод, использующий async / await?

Я видел много статей о том, как использовать async / await в ваших модульных тестах, но мне нужно прямо противоположное.

Как написать тест для метода, использующего async / await?

Моя спецификация не может достичь какого-либо кода после строки ожидания. В частности, спецификация не работает по двум причинам.

1) HelloWorld.otherCall возвращает undefined вместо указанного мной возвращаемого значения

2) HelloWorld.processResp никогда не вызывается

class HelloWorld {

    async doSomething(reqObj) {
        try {
           const val = await this.otherCall(reqObj);
           console.warn(val); // undefined
           return this.processResp(val);
        }
    }

}

describe('HelloWorld test', function () {

    let sut = new HelloWorld(); //gross simplification for demo purposes

    describe('doSomething()', function () {
        beforeEach(function mockInputs() {
           this.resp = 'plz help - S.O.S.';
        });

        beforeEach(function createSpy() {
            spyOn(sut, 'otherCall').and.returnValue( $q.resolve(this.resp) );
            spyOn(sut, 'processResp');
        });

        it('should call otherCall() with proper arguments', function () {
            //this test passes   
        });

        it('should call processResp() with proper arguments', function () {
           sut.doSomething({});
           $rootScope.$apply(); //you need this to execute a promise chain..

           expect(sut.processResp).toHaveBeenCalledWith(this.resp); 
           //Expected spy processResp to have been called with [ 'plz help SOS' ] but it was never called.
        });
    });
});

Запуск angular 1.5 и jasmine-core 2.6.


person user2954463    schedule 19.01.2018    source источник


Ответы (2)


.then обещания перегружен для обработки обещаний или значений, а await является синтаксическим сахаром для вызова then.

Таким образом, нет причин, по которым ваш шпион должен будет возвращать обещание или даже значение. Возврат вообще, даже если undefined, должен вызвать срабатывание await и запустить остальную часть вашей async функции.

Я считаю, что ваша проблема в том, что вы не дожидаетесь решения doSomething обещания, прежде чем пытаться проверить то, что оно произошло. Что-то вроде этого должно дать вам больше ориентиров.

it('should call processResp() with proper arguments', async function () {
   await sut.doSomething({});
   // ...
});
person skylize    schedule 01.02.2018

У Jasmine есть асинхронная поддержка. Вероятно, таким образом вы сможете найти решение.

Лично я считаю, что такие методы вообще не стоит тестировать.

Состояние тестирования означает, что мы проверяем, что тестируемый код возвращает правильные результаты.

Тестирование взаимодействий означает, что мы проверяем, правильно ли тестируемый код вызывает определенные методы.

В большинстве случаев состояние тестирования лучше.

На вашем примере

async doSomething(reqObj) {
    try {
       const val = await this.otherCall(reqObj);
       return this.processResp(val);
    }
}

Пока otherCall и processResp хорошо охвачены модульными тестами, ваше хорошее.

Что-то должно быть покрыто тестами e2e.

вы можете узнать об этом больше на http://spectory.com/blog/Test%20Doubles%20For%20Dummies

person Guy Yogev    schedule 22.01.2018