Preface
Which kind of method is the easiest to test? In my opinion, the answer is like this:
哪种方法最易于测试呢?在我看来,答案应该是这样的:
case1 function(s) {
return s.split(' ').join('.');
}
It is a pure functional method, which can be tested as easily as below:
这是一个典型的函数式编程, 它的测试很简单:
assert.equal(case1('Sue Zh'), 'Sue.Zh')
Another method easy to test is that can change something global, like:
另一种更改全局属性的方法也像上述方法那样:
case2 function(s) {
this.set('name', s.split(' ').join(',');
}
Similarly, it can be tested as easily as below:
同样地, 它的测试也很简单
case2('Sue Zh');
assert.equal(this.name, 'Sue.Zh');
How to test other kind of methods, such as that only invoke some methods and doesn't return anything or that always throws errors in testing environment, etc. If you are faced with these problems, it's a good idea to try Sinon.JS.
那么,其他种类的方法要怎么测试呢, 比如只调用其它方法, 不返回任何值的方法? 再比如在测试环境一直报错的方法?如果你正面临这样的问题,不妨试试Sinon.JS。
Let me introduce Sinon.JS to you in detail by giving some simple cases.
让我通过一些简单的案例详细介绍一下Sinon.JS
Case3
case3 function(s) {
this.anotherMethod1(s.length);
this.anotherMethod2(s.length+1);
}
what aspects should we test on this method?
对于这个方法,在单元测试的时候,我们关心什么呢?
- if the two methods invoked
anotherMethod1与anotherMethod2是否被调用 - if the two methods invoked with corrent parameters
是否向两个方法传入了正确的参数
By Sinon, we can test the two aspects by spy:
通过Sinon,我们可以通过spy测试它们:
let spy1 = sinon.spy(this, 'anotherMethod1');
let spy2 = sinon.spy(this, 'anotherMethod2');
case3('Sue Zh');
assert.ok(spy1.calledWith(6));
assert.ok(spy2.calledWith(7));
What's spy?
It is like a spy you assign to spy a method, which would record something during the method's invocation.
spy就像一个你委托去监视某一个方法的侦探,它会在方法调用期间窥探出你想要的信息。
What else can spy do?
-
called, notCalled
If the spy was called.
是否spy窥探的方法被调用。 -
calledOnce, calledTwice, calledThrice, callCount
How many times the spy was called.
spy窥探的方法被调用的次数。 -
firstCall, secondCall, thirdCall, lastCall, getCall(n), getCalls()
Get a specific call or all calls
获得某一个或所有的调用。 -
calledBefore(anotherSpy), calledAfter(anotherSpy), calledImmediatelyBefore(anotherSpy), calledImmediatelyAfter(anotherSpy)
the order of spies called
检查各个spy窥探的方法调用的顺序。 -
calledWith(arg1, ...), alwaysCalledWith(arg1, ...), calledWithExactly(arg1, ...), alwaysCalledWithExactly(arg1, ...), calledWithMatch(arg1, ...), neverCalledWith(arg1, ...)
Check if the spy was exactly, always or never called with args that given or can match.
检查spy窥探的方法是否被传入了正确的参数。 -
returned(obj), alwaysReturned(obj)
Check if the spy returned the provided value
检查spy窥探的方法是否返回了期望的值 -
threw(null|String|Object), alwaysThrew(null|String|Object)
,
Check if the spy threw exceptions
检查spy窥探的方法是否抛出了异常 -
withArgs(arg1, ...)
Filter a spy that only spies method invoked with given parameters.
过滤出窥探的方法被传入了制定参数的spy -
thisValues
各个spy窥探的方法中的this
Note that a spy just can spy a method, it is not able to do anything to change the invocation of a method.
请注意spy只能窥探一个方法,它并不能改变方法调用本身。
Case4
case4 function(s) {
this.anotherMethod1(s.length); //threw an Exception
this.anotherMethod2(s.length);//send a XMLHttpResquest
}
We also want to test the two aspects as above, however, as you can see, anotherMethod1 throws an error in testing environment, and anotherMethod2 sends a request which may have side effects, what we can do is to try sinon.stub:
针对上面这个方法,我们想测试同样两个方面, 然而,你会发现, anotherMethod1在测试环境下抛出异常, anotherMethod2会发出一个网络请求,这个网络请求可能会出现异常,我们可以尝试sinon.stub:
let spy1 = sinon.stub(this, 'anotherMethod1');
let spy2 = sinon.stub(this, 'anotherMethod2');
case4('Sue Zh');
assert.ok(spy1.calledWith(6));
assert.ok(spy2.calledWith(6));
What's stub?
It is a special kind of spy, but can do more than a pure spy. It creates another method with pre-programmed behavior to replace case4.
Stub是一种特殊的spy, 但是具有很强的干涉性。它创建了另一个方法替代case4, 可以给另一个方法一些预设定的行为。
Difference between spy and stub?
A pure spy just spy a method and won't block it but a stuck is a kind of spy that will block a method after it accepts parameters.
单纯的spy只是窥探方法并不会阻碍它的执行,而stub则是一种会阻止原始方法执行的spy。
What else can stub do?
-
onCall(n), onFirstCall(), onSecondCall(), onThirdCall()
When called at some time
当发生某一次调用时 -
returns(obj), returnsArg(index), returnsThis()
Makes the stub return the provided value.
使stub返回某个值/某次调用的传入参数/调用时的this -
restore()
Recovers the method or obj changed by stub
恢复对象或者对象的方法使其可以被正常调用 -
value()
Assigns a new value to a variable
给对象的某一个属性赋值 -
set(setterFn) get(getterFn)
Defines a new setter or getter for the stub callThrough()
throws(null|String|Object)