Обработчик юнит-теста, содержащий обещание - PullRequest
0 голосов
/ 22 октября 2019

У меня есть знания TDD, и я пытался запустить проект в javascript, используя те же принципы.

Я создаю API, который, при попадании, запускает запрос к внешней службе, чтобычтобы собрать некоторые данные и, после получения, проанализировать их и вернуть ответ.

До сих пор мне не повезло с сагой, я много искал и самую похожую проблему в SOнашел это один . Но я не добился успеха в применении того же решения.

Моя реализация на стороне реализации выглядит следующим образом:

//... other handlers
weather(request, response) {
    //... some setup and other calls
    this.externalService.get(externalURL)
        .then(serviceResponse => {
            this.externalResponseParser.parse(serviceResponse)
        });
    //... some more code
}

И на стороне теста:

let requester;
let mockParser;
let handler;
let promiseResolve;
let promiseReject;

beforeEach(function () {
    requester = new externalRequesterService();
    mockParser = sinon.createStubInstance(...);

    handler = new someHandler({
        externalService: requester,
        externalResponseParser: mockParser
    });
});

it('returns data', function () {
    sinon.stub(requester, 'get').callsFake((url) => {
        return new Promise((resolve, reject) => {
            // so I can be able to handle when the promise gets resolved
            promiseResolve = resolve;
            promiseReject = reject;
        });
    });

    handler.weather(request, response);

    // assertions of what happens before externalService.get gets called - all green

    promiseResolve(expectedServiceResponse);

    assert.ok(mockExternalResponseParser.parse.calledOnce, 'Expected externalResponseParser.parse to have been called once');
});

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

Я пытался выяснить, есть ли какой-нибудь eventually, который можно использовать, поэтому мое утверждение после выполнения обещания будет выглядеть примерно так:

assert.eventually(mockExternalResponseParser.parse.calledOnce, 'Expected externalResponseParser.parse to eventually be called once');

, но не повезло.

У кого-нибудь есть четкое объяснение того, чего не хватает? Большое спасибо заранее

PS - По запросу, пожалуйста, найдите урезанную версию моего кода здесь . Просто запустите npm install, а затем npm test, чтобы получить тот же вывод.

1 Ответ

0 голосов
/ 10 ноября 2019

Спасибо всем за потраченное время.

В итоге я нашел эту очень хорошую статью о Средняя , которая позволила мне решить мою проблему. У него есть очень хорошее объяснение, переходящее от обратных вызовов к обещаниям, и это был именно тот сценарий, который у меня был в руках.

Я обновил репозиторий github , который я создал, о том, как это исправить.

Если вы хотите TL; DR , то здесь просто выделение изменений. Сторона реализации:

async weather(request, response) {
    //...

    let serviceResponse = await this.requesterService.get(weatherURL);

    //...
};

А на стороне теста:

it('returns weather on success', async function () {
    sinon.stub(requester, 'get').callsFake((_) => {
        return new Promise((resolve, _) => {
            resolve(expectedServiceResponse);
        });
    });

    await handler.weather(request, response);

    //...
    assert.ok(mockWeatherParser.parseWeather.calledOnce, 'Expected WeatherParser.parseWeather to have been called once'); // no longer fails here
    //...
});

Теперь имейте в виду, что в этом примере это все еще синхронно. Тем не менее, я развивал свой API уже шаг за шагом, и после перехода на эту синхронную версию с помощью Promises было гораздо проще перейти на асинхронную версию. И с точки зрения тестирования, и с точки зрения реализации.

Если у вас возникла та же проблема и вам нужна помощь или у вас есть вопросы, дайте мне знать. Я буду рад помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...