В моих модульных тестах я хотел бы иметь возможность заменять элементы с издеваемыми элементами, а также предоставлять заглушки для методов исходного элемента.
Например, допустим, что шаблон моего компонента выглядит следующим образом:
<template>
<my-other-element id="myOtherElement"></my-other-element>
</template>
Скажем позже, в моем элементе я делаю что-то вроде этого:
myMethod: function () {
this.$.myOtherElement.foo();
}
Когда я пишу unit тест для своего элемента, я хотел бы сделать следующее:
<my-other-element>
foo()
Я нашел способ добиться этого, но почему-то это не кажется очень чистым. Мое текущее решение следующее:
var fooStub;
beforeEach(function () {
fooStub = sinon.stub();
replace('my-other-element').with('fake-my-other-element');
document.createElement('fake-my-other-element').constructor.prototype = {
foo: fooStub
};
element = fixture('basic');
});
Мне интересно, есть ли лучший способ достичь тех же результатов. Как-то создание пустого элемента, чтобы изменить свойство prototype
для добавления заглушек, кажется, не лучший способ.
И я знаю, что вы также можете это сделать:
stub('my-other-element', {
foo: fooStub
});
Но я предпочитаю всегда издеваться над всем, чтобы убедиться, что побочных эффектов от дочернего элемента нет.
есть несколько вариантов, которые я использовал. Одним из них является проактивное добавление этих методов к рассматриваемому элементу
chai.should();
suite('let\s stub a child method', () => {
let testView;
setup(() => {
replace('child-el').with('fake-child-el');
testView = fixture('basic');
testView.$.child.method = sinon.stub();
});
test('myMethod() calls child method', () => {
testView.myMethod();
testView.$.child.method.should.have.been.called;
});
});
Другим является создание поддельного элемента для заглушения и обертывания его методами
Polymer({is: 'fake-child-el', method: sinon.stub;});
chai.should();
suite('let\s stub a child method', () => {
let testView;
setup(() => {
replace('child-el').with('fake-child-el');
testView = fixture('basic');
});
test('myMethod() calls child method', () => {
testView.myMethod();
testView.$.child.method.should.have.been.called;
});
});
Это может не работать во всех браузерах.
EDIT: в тех случаях, когда второй подход завершился неудачно, я сделал методы stub-element вроде method:() => null
, а затем завернул этот метод в вызов sinon.stub() внутри набора тестов.
Я попробовал второй метод: Polymer({is: 'fake-child-el', method: sinon.stub;});
Он работает, но оператор может быть выполнен только один раз (поскольку элемент Polymer не может быть ни незарегистрирован, ни зарегистрирован во второй раз), и вы можете вызвать его более одного раза (например, чтобы изменить возвращаемое значение method
). Чтобы обойти это, вы можете сделать следующее:
let fakeChildEl;
let replaceChildEl = (methodReturnVal) => {
const methodStub = sandbox.stub().returns(methodReturnVal);
fakeChildEl = Polymer({
is: 'fake-child-el',
method: methodStub,
});
replace('child-el').with('fake-child-el');
replaceChildEl = (methodReturnVal) => {
const methodStub = sandbox.stub().returns(methodReturnVal);
fakeChildEl.prototype.method = methodStub;
replace('child-el').with('fake-child-el');
}
};
Тогда любой unit тест может вызвать replaceChildEl(variableReturnVal)
ready()
илиattached()
, вы не можете смоделировать подобные методы. Второй вариант может также работать. Может быть, это самый чистый. Спасибо