2017-02-22 12 views
3

Я пытаюсь написать тест в JavaScript, метод я тестирование делает 2 вызовов методов (model.expandChildren() и view.update();)Mocking из нескольких вызовов методы с использованием жасмина

// inside 'app'/'RV.graph' 
var expandChildren = function(){ 
    return model.expandChildren().then(function(r) { 
     view.update(r); 
    }); 
}; 

Я попытался использовать спецификации Jasmine, чтобы написать тест для просмотра функций представления и модели, но, похоже, у вас может быть только один шпион в данном тесте. Кажется, что мне не хватает чего-то большого здесь и что должен быть способ издеваться над несколькими вызовами методов с использованием шпионов, так как моя функция должна выполнять оба этих вызова.

Я хочу, чтобы мой spec мог работать так, как показано ниже, но в настоящее время он проходит только первый тест (первый шпион работает как ожидалось), второй тест терпит неудачу, потому что Жасмин пытается запустить фактическую функцию, а не шпионская функция:

var model = GRAPH.model; 
var view = GRAPH.view; 
var app = RV.graph; 

describe('#expandChildren', function() { 

    beforeEach(function() { 
     // first spy, all good 
     spyOn(model, 'expandChildren').and.callFake(function() { 
      return new Promise(function(resolve) { 
      resolve(testResponse); 
      }); 
     }); 
     // second spy doesn't work because Jasmine only allows 1 
     spyOn(view, 'update'); 
     app.expandChildren(); 
    }); 

    // passing test 
    it('calls model.expandChildren', function() { 
     expect(model.expandChildren).toHaveBeenCalled(); 
    }); 

    // failing test that runs the REAL view.update method 
    it('calls view.update', function() { 
     expect(view.update).toHaveBeenCalled(); 
    }); 
}); 

Есть ли способ сделать это с помощью жасмина?

ответ

1

Помните, что вы работаете с асинхронными вызовами. Первый вызов синхронный, поэтому он записывается, а второй - только позже. Дайте себе контроль над ситуациями. Я обычно использую шаблон, как это:

describe('#expandChildren', function() { 
    var resolver; 

    it('calls model.expandChildren', function(done) { 
     spyOn(model, 'expandChildren').and.callFake(function() { 
      return new Promise(function(resolve) { 
      resolver = resolve; 
      }); 
     }); 
     spyOn(view, 'update'); 

     app.expandChildren(); 

     expect(model.expandChildren).toHaveBeenCalled(); 
     expect(view.update).not.toHaveBeenCalled(); 

     resolver(); 
     done(); 

     expect(view.update).toHaveBeenCalled(); 
    }); 
}); 

Таким образом, спецификация будет работать только после того, как обещание было решены и done() был вызван.

+0

Решение, безусловно, еще одна проблема здесь, но даже с 'done() мой второй тест все еще не работает. Возможно, я ошибаюсь, но у меня создалось впечатление, что только один шпион может использоваться для каждого блока описания, даже если у вас несколько шпионов в наборе тестов. – khopsickle

+0

Нет ограничений в количестве шпионов, которые вы можете создать. Во всяком случае, одновременное решение обещания о создании может быть ранним. Я никогда не пробовал этот шаблон, но всегда решался вручную. Таким образом, вы дополнительно протестируете свой асинхронный код _is_, который будет выполнен позже. См. Отредактированный ответ. – ccprog