Шпионаж на конструктор с использованием жасмина
Я использую Jasmine для проверки того, созданы ли определенные объекты и на них вызывается метод.
У меня есть виджет jQuery, который создает объекты flipcounter и вызывает на них метод setValue. Код для flipcounter находится здесь: https://bitbucket.org/cnanney/apple-style-flip-counter/src/13fd00129a41/js/flipcounter.js
Флип-счетчики создаются с использованием:
var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500});
Я хочу проверить, что создаются flipcounters, и на них вызывается метод setValue. Моя проблема заключается в том, как я могу следить за этими объектами еще до их создания? Я шпионить за конструктором и возвращать поддельные объекты? Пример кода действительно поможет. Спасибо за вашу помощь!:)
Update:
Я пробовал следить за flipCounter следующим образом:
myStub = jasmine.createSpy('myStub');
spyOn(window, 'flipCounter').andReturn(myStub);
//expectation
expect(window.flipCounter).toHaveBeenCalled();
Затем тестирование для вызова setValue с помощью flipCounter:
spyOn(myStub, 'setValue');
//expectation
expect(myStub.setValue).toHaveBeenCalled();
первый тест для инициализации flipCounter в порядке, но для тестирования вызова setValue все, что я получаю, это метод 'setValue() не существует'. Правильно ли я делаю это? Спасибо!
Ответы
Ответ 1
flipCounter
- это еще одна функция, даже если она также создает объект. Следовательно, вы можете:
var cSpy = spyOn(window, 'flipCounter');
чтобы получить шпион на нем, и делать всевозможные проверки на нем или сказать:
var cSpy = spyOn(window, 'flipCounter').andCallThrough();
var counter = flipCounter('foo', options);
expect(cSpy).wasCalled();
Однако это кажется излишним. Этого было бы достаточно:
var myFlipCounter = new flipCounter("counter", options);
expect(myFlipCounter).toBeDefined();
expect(myFlipCounter.getValue(foo)).toEqual(bar);
Ответ 2
Я бы предложил использовать jasmine.createSpyObj()
, когда вы хотите издеваться над объектами со свойствами, которые нужно отслеживать.
myStub = jasmine.createSpyObj('myStub', ['setValue']);
spyOn(window, 'flipCounter').andReturn(myStub);
Это проверяет взаимодействие с ожидаемым интерфейсом flipCounter
, не зависящим от реализации flipCounter
.
Ответ 3
Вам нужно реализовать поддельный конструктор для flipCounter
, который устанавливает свойство setValue
в функцию-шпион. Скажем, функция, которую вы хотите проверить, такова:
function flipIt() {
var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500});
myFlipCounter.setValue(100);
}
Ваша спецификация должна выглядеть так:
describe('flipIt', function () {
var setValue;
beforeEach(function () {
setValue = jasmine.createSpy('setValue');
spyOn(window, 'flipCounter').and.callFake(function () {
this.setValue = setValue;
});
flipIt();
});
it('should call flipCounter constructor', function () {
expect(window.flipCounter)
.toHaveBeenCalledWith("counter", {inc: 23, pace: 500});
});
it('should call flipCounter.setValue', function () {
expect(setValue).toHaveBeenCalledWith(100);
});
});
Ответ 4
Следующее не зависит от "окна". Допустим, это код, который вы хотите проверить -
function startCountingFlips(flipCounter) {
var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500});
}
Ваш тест может быть -
var initSpy = jasmine.createSpy('initFlipCounter');
var flipCounter = function(id, options) {
initSpy(id, options);
}
startCountingFlips(flipCounter);
expect(initSpy).toHaveBeenCalledWith("counter", {inc:23, pace:500});
Ответ 5
Моя версия для проверки конструктора заключается в том, чтобы заглянуть в прототип:
spyOn(flipCounter.prototype, 'setValue').and.callThrough();
var myFlipCounter = new flipCounter("counter", {inc: 23, pace: 500});
expect(flipCounter.prototype.setValue).toHaveBeenCalledTimes(1);
Ответ 6
Не знаю, как это сделать, используя jasmine mocks, но если вам нужны мощные mocking/spy/stubs, я рекомендую sinon.js, который отлично работает с жасмином.
Из документов:
Контрольный шпион - это функция, которая записывает аргументы, возвращаемое значение, значение этого и исключенного броска (если есть) для всех его вызовов. Тест шпион может быть анонимной функцией или может обернуть существующую функцию.
Mocks (и издевательские ожидания) - это поддельные методы (например, шпионы) с предварительно запрограммированное поведение (например, заглушки), а также запрограммированные ожидания. Макет провалит ваш тест, если он не используется как ожидается.
С помощью sinon.js вы можете создать макет конструктора flipCounter, который возвращает другой шпион.
Затем утверждаем, что конструктор вызывается с помощью constructorMock.calledWithNew() и утверждает, что возвращенный шпион вызывался с возвратом возвращаемого spy.calledWith(arg1, arg2...).