Используйте Jasmine, чтобы заглушить обратные вызовы JS на основе значений аргументов

В моем приложении node.js есть метод JS, который я хочу выполнить модульное тестирование. Он делает несколько вызовов метода сервиса, каждый раз передавая этот сервис обратный вызов; обратный вызов накапливает результаты.

Как я могу использовать Jasmine, чтобы заглушить метод службы, чтобы при каждом вызове заглушки вызывался обратный вызов с ответом, определяемым аргументами?

Это (как) метод, который я тестирую:

function methodUnderTest() {

    var result = [];
    var f = function(response) {result.push(response)};

    service_method(arg1, arg2, f);

    service_method(other1, other2, f);

    // Do something with the results...
}

Я хочу указать, что когда service_method вызывается с arg1 и arg2, заглушка будет вызывать обратный вызов f с конкретным ответом, а когда она вызывается с other1 и other2, она будет вызывать тот же самый обратный вызов с другим конкретным ответом.

Я бы тоже рассмотрел другую структуру. (Я попробовал Nodeunit, но не смог сделать то, что хотел.)

3 ответа

Вы должны быть в состоянии использовать callFake шпионская стратегия. В Жасмин 2.0 это будет выглядеть так:

describe('methodUnderTest', function () {
  it("collects results from service_method", function() {
    window.service_method = jasmine.createSpy('service_method').and.callFake(function(argument1, argument2, callback) {
      callback([argument1, argument2]);
    });

    arg1 = 1, arg2 = 'hi', other1 = 2, other2 = 'bye';
    expect(methodUnderTest()).toEqual([[1, 'hi'], [2, 'bye']]);
  });
});

куда methodUnderTest возвращает массив результатов.

Поскольку я не уверен, что вы тестируете правильную вещь здесь, вы можете использовать шпион и вызвать spy.argsForCall.

var Service = function () {
};

Service.service_method = function (callback) {
  someAsyncCall(callback);
};

function methodUnderTest() {

    var result = [];
    var f = function(response) {result.push(response)};

    Service.service_method(arg1, arg2, f);

    Service.service_method(other1, other2, f);

}

в вашем тесте:

it('should test something', function () {
  spyOn(Service, 'service_method');
  methodUnderTest()
  var arg1 = Service.argsForCall[0][0];
  var arg2 = Service.argsForCall[0][1];
  var f = Service.argsForCall[0][2];
  if(arg1==condition1 && arg2==condition2){f(response1)}

});

Вы не можете заглушить это как есть, потому что оно является внутренним для метода.

Вы проверяете не то, что здесь. methodUnderTest следует проверить, убедившись, что результаты обрабатываются правильно. Обеспечение этого service_method выполняет обратный вызов с конкретными аргументами - это еще один тест, который должен быть проверен независимо.

Теперь спецификация для methodUnderTest может быть просто о том, что происходит после этого обратного вызова. Не беспокойтесь, если обратные вызовы работают, потому что вы уже проверяли это в другом месте. Просто беспокойтесь о том, что метод делает с результатами обратного вызова.

Даже если service_method это из библиотеки или программного кода, который вы не контролируете напрямую, это все еще применяется. Основное правило - проверять код, который вы сами пишете, и полагать, что другие библиотеки следуют тому же правилу.

Другие вопросы по тегам