Sinon.JS
※ 加筆中
- HTML5 APIs
- UI ライブラリ
- テスト支援
- ドキュメント
- コード品質ツール
- バリデータ
- キー入力支援
- テストダブル
- ハイブリッドアプリケーション
- 継続的インテグレーション
- Sinon.JSとは
- 使用方法
- Spy
- Stub
- Mock
- Expectations
- Fake Timer
- Fake XMLHttpRequest
- Fake Server
- API
- var server = sinon.fakeServer.create()
- var server = sinon.fakeServerWithClock.create()
- server.respondWith(String|Array|Function response)
- server.respondWith(String url, String|Array|Function response)
- server.respondWith(String method, String url, String|Array|Function response)
- server.respondWith(RegExp urlRegExp, String|Array|Function response)
- server.respondWith(String method, RegExp urlRegExp, String|Array|Function response)
- server.respond()
- server.autoRespond
- server.autoRespondAfter
- server.fakeHTTPMethods
- server.getHTTPMethod(Object request)
- server.restore()
- API
- Assertion
- Matcher
- Sandbox
- Utility
Sinon.JSとは
テスト対象が依存しているモジュールやリソースの代役を務めてくれるライブラリです。
Sinon.JSは大きくわけて以下のAPIを持っています。
- Spy
- Stub
- Mock
- Fake timer
- Fake XmlHttpRequest
- Fake server
- Assertion
- Matcher
- Sandbox
- Utility
なお、Sinonは「シノン」と読むそうで、トロイ戦争で活躍したスパイの名前が由来とのこと。
使用方法
Spy
Spyはあるメソッドの代替として動作し、
- 引数に何が渡されたか、
- どのような戻り値を返したか、
- 自身が何回呼び出されたか
等、実行結果に関する詳細な情報を持ちます。
API
var spy = sinon.spy()
function now(fn) {
fn(+new Date());
}
now(spy);
// spyオブジェクトが実行されたか
console.log(spy.called); // true
// spyオブジェクトが実行された回数
console.log(spy.callCount); // 1
// spyオブジェクトに渡された値
console.log(spy.args[0]); // [1378948520055] (現在時刻のミリ秒を持つ配列)
var spy = sinon.spy(Function testFunc)
var code = null;
switch (name) {
case 'red':
code = '#f00';
break;
case 'green':
code = '#080';
break;
case'yellow':
code = '#ff0';
break;
case 'white':
code = '#fff';
break;
}
return code;
}
var spy = sinon.spy(getRgb);
spy('red');
console.log(spy.called); // true
console.log(spy.returnValues); // ['#ff0']
console.log(spy.callCount); // 1
spy.reset();
var spy = sinon.spy(Object obj, String methodName)
twice: function(num) {
return num * 2;
},
half: function(num) {
return num / 2;
}
};
var spy = sinon.spy(obj, 'twice');
spy(10);
console.log(spy.called); // true
console.log(spy.returnValues); // [20]
console.log(spy.callCount); // 1
その他のAPI
名前 | 戻り値 | 説明 |
---|---|---|
callCount | Number | 実行された回数 |
called | Boolean | 実行されたか |
calledOnce | Boolean | 1回実行されたか |
calledTwice | Boolean | 2回実行されたか |
calledThrice | Boolean | 3回実行されたか |
firstCall | Objectt(実行結果の情報) | 1回目に実行されたときの結果情報を取得する |
secondCall | Objectt(実行結果の情報) | 2回目に実行されたときの結果情報を取得する |
thirdCall | Objectt(実行結果の情報) | 3回目に実行されたときの結果情報を取得する |
lastCall | Objectt(実行結果の情報) | 最後に実行されたときの結果情報を取得する |
calledBefore(anotherSpy) | Boolean | 指定したSpyオブジェクトよりも前に自身が実行されたか |
calledAfter(anotherSpy) | Boolean | 指定したSpyオブジェクトよりも後に自身が実行されたか |
calledOn(Object thisValue) | Boolean | 指定したオブジェクトが、自身のコンテキストと同じか |
alwaysCalledOn(ObjectthisValue) | Boolean | 指定したオブジェクトが、今まで実行した全てのメソッドのコンテキストと同じか |
calledWith(arg1, arg2, ...) | Boolean | メソッド実行時の引数が、指定した値と完全(厳密等価比較)に一致しているか |
alwaysCalledWith(arg1, arg2, ...) | Boolean | 全ての実行において、メソッド実行時の引数が指定した値と同じか |
calledWithExactly(arg1, arg2, ...) | Boolean | メソッド実行時の引数の内容と長さが指定した値と同じか |
alwaysCalledWithExactly(arg1, arg2, ...) | Boolean | 全ての実行において、メソッド実行時の引数の内容と長さが指定した値と同じか |
calledWithMatch(arg1, arg2, ...) | Boolean | メソッド実行時の引数のそれぞれの値が、指定した値と完全に一致しているか |
alwaysCalledWithMatch(arg1, arg2, ...) | Boolean | 全ての実行において、メソッド実行時の引数の値が、指定した値と完全に一致しているか |
calledWithNew() | Boolean | スパイでnew演算子が呼ばれたか |
neverCalledWith(arg1, arg2, ...) | Boolean | このメソッドに指定したいずれかの引数と、テストメソッド実行時の引数が同じでないこと |
neverCalledWithMatch(arg1, arg2, ...) | Boolean | このメソッドに指定した全ての引数と、テストメソッド実行時の引数が同じでないこと |
threw() | Boolean | 一回以上例外をスローしたか |
threw("TypeError") | Boolean | 指定した型のエラーを1回以上スローしたか |
threw(obj) | Boolean | 指定したエラーオブジェクトで1回以上スローしたか |
alwaysThrew() | Boolean | 全ての実行に置いて、例外をスローしたか |
alwaysThrew("TypeError") | Boolean | 全ての実行に置いて、指定した型のエラーをスローしたか |
returned(Objet anyValue) | Boolean | 引数に指定した値が、Spyメソッドが直前で返した値と一致するか |
alwaysReturned(Objet anyValue) | Boolean | テスト対象のメソッドが常に引数で指定した値を返しているか |
spy.getCall(Number index) | Objectt(実行結果の情報) | X回目の結果情報を取得する |
thisValues | Array[Object, ...] | Spyがテストしたメソッドのコンテキスト(thisの値) |
args | Array[Object, ...] | Spyオブジェクトに渡されたパラメータの値 |
exceptions | Array[Object, ...] | Spy化したメソッドでスローされたエラーオブジェクトを持つ配列 |
returnValues | Array[Object, ...] | Spy化したメソッドが返した値 |
reset() | Void | Spy化したメソッドを元の状態に戻す |
printf(String formatString, [arg1, arg2, ...]) | String | 指定したフォーマットで文字列を出力します |
Stub
Stubは、ある機能をテストするために必要な別機能の代替として動作します。
Spyは主に実行結果に関する情報のみを持っていますが、StubはSpyの機能に加えてある条件の場合は例外をスローする、この引数の場合はこの値を返す、といったように振る舞いを変更する機能を持っています。
API
var stub = sinon.stub()
anonymousメソッドのスタブを生成します
stub.withArgs(42).returns(1);
stub.withArgs(1).throws('HogeError', '例外発生!');
console.log(stub()); // undefined
console.log(stub(42)); // 1
try {
stub(1); // HogeErrorがスローされる
} catch(e) {
console.log(e.message); // 例外発生!
}
var stub = sinon.stub(Object obj, String methodName)
第一引数のオブジェクトが持つ、第二引数に指定された名前のメソッドを、スタブに差し替えます。
もとのメソッドに戻す場合は、obj[methodName].restore()またはstub.restore()を実行します。
this.ar = [];
};
ModuleA.prototype.calc = function(data) {
this.ar.push(data.calculate());
};
ModuleA.prototype.result = function(data) {
return this.ar.join(',');
};
function TestData(num) {
this.num = num;
}
TestData.prototype.calculate = function() {
// 未実装 Stubで代替を用意する
};
var testData = new TestData(10);
var modA = new ModuleA();
var stub = sinon.stub(testData, 'calculate');
modA.calc(testData);
console.log(testData.calculate.returnValues[0] === modA.ar[0]); // true
testData.calculate.restore(); // スタブ機能を削除する
var stub = sinon.stub(Object obj, String methodName, Function func)
第一引数のオブジェクトが持つ、第二引数に指定された名前のメソッドを、第三引数のメソッドに差し替えます。
もとのメソッドに戻す場合は、obj[methodName].restore()またはstub.restore()を実行します。
this.ar = [];
};
ModuleA.prototype.calc = function(data) {
this.ar.push(data.calculate());
};
ModuleA.prototype.result = function(data) {
return this.ar.join(',');
};
function TestData(num) {
this.num = num;
}
TestData.prototype.calculate = function() {
// 未実装 Stubで代替を用意する
};
var testData = new TestData(10);
var modA = new ModuleA();
var stub = sinon.stub(testData, 'calculate', function() {
return parseInt(Math.random() * 10);
});
modA.calc(testData);
console.log(testData.calculate.returnValues[0] === modA.ar[0]); // true
stub.restore(); // スタブ機能を削除する (stub.calculate.restore()でも可)
var stub = sinon.stub(obj)
指定したオブジェクトにスタブ機能を付与します。
もとのオブジェクトの状態に戻す場合は、obj[メソッド名].restore()またはstub.restore()を実行します。
this.ar = [];
};
ModuleA.prototype.calc = function(data) {
this.ar.push(data.calculate());
};
ModuleA.prototype.result = function(data) {
return this.ar.join(',');
};
function TestData(num) {
this.num = num;
}
TestData.prototype.calculate = function() {
// 未実装 Stubで代替を用意する
};
var testData = new TestData(10);
var modA = new ModuleA();
var stub = sinon.stub(testData);
modA.calc(stub);
console.log(stub.calculate.returnValues[0] === modA.ar[0]); // true
stub.restore(); // スタブ機能を削除する (stub.calculate.restore()でも可)
その他のAPI
名前 | 戻り値 | 説明 |
---|---|---|
stub.withArgs(arg1, arg2, ...) | Stub | 引数によってStubの振る舞いを変えたい場合にその引数を設定します |
stub.returns(Object returnValue) | Stub | Stubが返すべき値を設定します |
stub.returnsArg(Number index) | Stub | このメソッドでインデックスを設定後、引数を指定してStubを実行すると、Stubはこの引数のindex番目を戻り値として返します |
stub.throws() | Stub | Stubが例外をスローするよう設定します |
stub.throws(String ErrorType) | Stub | 引数に指定した型のエラーをスローするよう設定します |
stub.throws(Object throwObj) | Stub | 引数に指定したエラーオブジェクトをスローするよう設定します |
stub.callsArg(Number index) | Stub | このメソッドでインデックスを設定後、引数を指定してStubを実行すると、Stubはこの引数のindex番目をコールバック関数として実行します |
stub.callsArgOn(Number index, Object context) | Stub | このメソッドでインデックスを設定後、引数を指定してStubを実行すると、Stubはcontextに指定したオブジェクトをthisに設定して、Stubに指定した引数のindex番目をコールバック関数として実行します。 |
stub.callsArgWith(Number index, arg1, arg2, ...) | Stub | このメソッドでインデックスを設定後、引数を指定してStubを実行すると、StubはcallsArgWith()の第二引数以降の値を引数としてStubに指定した引数のindex番目をコールバック関数として実行します |
stub.callsArgOnWith(Number index, Object context, arg1, arg2, ...) | Stub | このメソッドでインデックスを設定後、引数を指定してStubを実行すると、StubはcallsArgOnWith()の第二引数に指定したオブジェクトをコンテキスト(this)に、第三引数以降の値を引数として、Stubに指定した引数のindex番目をコールバック関数として実行します |
stub.yields(arg1, arg2, ...) | Stub | callsArg()に似ています。異なる点はユーザがコールバックとして実行してほしい引数のインデックス番号を指定しないところです。Stubに指定した引数の中から最初に見つかった関数のみを実行します。 |
stub.yieldsOn(context, arg1, arg2, ...) | Stub | callsArgOn()に似ています。異なる点はユーザがコールバックとして実行してほしい引数のインデックス番号を指定しないところです。Stubに指定した引数の中から最初に見つかった関数のみを実行します。 |
stub.yieldsTo(property, arg1, arg2, ...) | Stub | yields()に似ています。異なる点は第一引数にオブジェクトのプロパティ名を指定するところです。Stubの引数にはオブジェクトを指定します。指定したオブジェクトからpropertyに指定したプロパティの値(コールバック)を実行します。 |
stub.yieldsToOn(property, context, arg1, arg2, ...) | Stub | コールバックのコンテキストを第二引数に指定する以外はyieldsTo()と同じです。 |
stub.yield(arg1, arg2, ...) | Stub | このメソッドに指定された引数Stubの引数に指定されたコールバックを全て実行します。 |
stub.yieldTo(Function callback, arg1, arg2, ...) | Stub | |
stub.callArg(argNum) | インデックス番号を指定してStubの引数に指定したコールバックを実行します | |
stub.callArgWith(argNum, args1, arg2, ...) | Stub | Stubの引数に指定したindex番目のコールバックを実行します。実行されたコールバックの引数にはcallArgWith()の第二引数以降に指定した値が渡されます。 |
stub.callsArgAsync(Number index) | Stubの引数に指定したindex番目のコールバックを非同期で実行します。 | |
stub.callsArgOnAsync(Number index, Object context) | Stub | contextに指定したオブジェクトをthisに設定して、Stubの引数に指定したindex番目のコールバックを非同期で実行します。 |
stub.callsArgWithAsync(Number index, arg1, arg2, ...) | Stub | インデックス番号を指定してStubの引数に指定したコールバックを非同期実行します。実行されたコールバックの引数にはcallsArgWithAsync()の第二引数以降に指定した値が渡されます。 |
stub.callsArgOnWithAsync(Number index, Object context, arg1, arg2, ...) | Stub | 非同期でcallsArgOnWith()を実行します |
stub.yieldsAsync(Arrary args) | Stub | 非同期でyields()を実行します |
stub.yieldsOnAsync(Object context, Array args) | Stub | 非同期でyieldsOn()を実行します |
stub.yieldsToAsync(String property, Array args) | Stub | 非同期でyieldsTo()を実行します |
stub.yieldsToOnAsync(String property, Object context, Array args) | Stub | 非同期でyieldsToOn()を実行します |
Mock
Mockは、Stubの機能に加えて設定した期待値どおりにメソッドが実行されたかを検証する機能を持っています。
API
var mock = sinon.mock(obj)
引数に指定したオブジェクトからMockオブジェクトを生成します。
var expectation = mock.expects("method")
引数に指定したメソッド名を持つメソッドに、MockのExpectation(検証機能)を付与します。
メソッドからExpectationを除去する場合は、mock.restore()を実行します。
mock.expects("ajax").atLeast(2).atMost(5);
mock.verify();
mock.restore();
mock.verify()
Expectationに指定した条件通りにメソッドが実行されたかを検証します。
実行されていないと例外をスローします。
var mock = sinon.mock(myAPI);
mock.expects("func1").twice(); // メソッドfunc1が2回実行されることを期待値に設定
myAPI.func1();
mock.verify(); // func1が2回実行されたか検証する
上記の場合、mock.verify()を実行すると
例外がスローされて、期待値と実行結果が一致していないことを知らせます。
Expectations
Mock.verify()での検証に必要な期待値を設定できます。
Mock.expects()を実行すると、Expectationオブジェクトを取得できます。
API
名前 | 戻り値 | 説明 |
---|---|---|
expectation.atLeast(Number number) | Expectation | 呼び出される最小回数を期待値として設定します |
expectation.atMost(Number number) | 〃 | 呼び出される最大回数を期待値として設定します |
expectation.never() | 〃 | 呼び出されないことを期待値として設定します |
expectation.once() | 〃 | 1度のみ呼び出されることを期待値として設定します |
expectation.twice() | 〃 | 2度呼び出されることを期待値として設定します |
expectation.thrice() | 〃 | 3度呼び出されることを期待値として設定します |
expectation.exactly(Number number) | 〃 | 呼び出される回数を期待値として設定します |
expectation.withArgs(arg1, arg2, ...) | 〃 | 指定した引数で呼び出されることを期待として設定します |
expectation.withExactArgs(arg1, arg2, ...) | 〃 | 指定した引数以外で呼び出されることを期待値として設定します |
expectation.on(obj) | 〃 | 実行したメソッドのコンテキスト(this)が引数で指定したオブジェクトであることを期待値として設定します |
Fake Timer
Fake TimerはsetTimeout()、clearTimeout()、setInterval()、clearInterval()とDateオブジェクトの時間を操作することができます。
API
var clock = sinon.useFakeTimers()
現在時刻を開始時間とする、Clockオブジェクトを生成します。
このメソッドを実行すると、setTimeout()、clearTimeout()、setInterval()、clearInterval()とDateオブジェクトはSinonによって書き換えられます。
これを、元に戻すにはclock.restore()または、[setTimeout|clearTimeout|setInterval|clearInterval].clock.restore()を実行します。
setTimeout(function() {
alert('Hello!'); // tick()で2000ms経過したものとして即座にアラートが実行される
}, 2000);
clock.tick(2000); // 2000ms経過させる
var clock = sinon.useFakeTimers(Number millis)
引数に指定された時刻を開始時間とする、Clockオブジェクトを生成します。
var clock = sinon.useFakeTimers([Number now, ] String prop1, String prop2, ...)
引数に指定された時刻を開始時間とする、Clockオブジェクトを生成します。
第二引数以降には、操作したいメソッド名(setTimeout、clearTimeout、setInterval、clearInterval)を指定します。
clock.tick(Number ms);
引数に指定した時間(ミリ秒)分、時間を経過させます。
経過したことにより影響を受けたタイマーは全て実行されます。
Fake XMLHttpRequest
XMLHttpRequest(XHR)を模倣した、動作を自由に操作するためのインターフェースを提供します。
通常はこのAPIを単体で使用することなく、後述のFake Serverとセットで使用します。
IEでこのAPIを使用する場合は、sinon.js(最新版はsinon-1.7.3.js)のあとにsinon-ie.js(最新版はsinon-ie-1.7.3.js)を読み込む必要があります。
API
var xhr = sinon.useFakeXMLHttpRequest()
ネイティブのXHRを書き換えて、XHRを模倣するFakeXMLHttpRequestオブジェクトを生成します。
元のXHRに戻したい場合は、xhr.restore()を実行します。
xhr.onCreate = function (FakeXMLHttpRequest xhr) {}
$.ajax()等でXHRが生成されたタイミングで、onCreateプロパティに設定したコールバックメソッドが実行されます。
FakeXMLHttpRequest
useFakeXMLHttpRequest()が返す値とonCreateに指定したコールバック関数が返す値は両方ともFakeXMLHttpRequestですが、持っているプロパティが異なるため、使用時する際には注意が必要です。
FakeXMLHttpRequest(useFakeXMLHttpRequest()が返すオブジェクト)
名前 | 戻り値 | 説明 |
---|---|---|
restore() | Void | FakeXMLHttpRequestの機能を除去して、ネイティブのXHRに戻します。 |
useFilters | Boolean | addFilter()を実行するかのフラグを設定します。デフォルトはfalseです。 |
addFilter(Function(String method, String url, Boolean async, String username, String password)) | Void | xhr.open()が実行される直前に実行されるコールバックメソッドを追加します。 |
FakeXMLHttpRequest(onCreateのコールバック関数が返すオブジェクト)
名前 | 戻り値 | 説明 |
---|---|---|
url | String | URL |
method | String | メソッド名 |
requestHeaders | Object | リクエストヘッダの全ての情報 |
requestBody | String | リクエストボディ |
status | Number | ステータス |
statusText | String | ステータス情報 |
async | Boolean | 非同期通信であるかのフラグ |
username | String | ユーザ名 |
password | String | パスワード |
getResponseHeader(String headerName) | String | レスポンスヘッダを取得します |
getAllResponseHeaders() | Array | 全てのヘッダ情報を取得します |
setResponseHeaders(Object headerDef) | Void | レスポンスヘッダを設定します |
setResponseBody(String body) | Void | レスポンスボディを設定します |
setRequestHeader(String headerName, String value) | Void | ヘッダ名と値を指定してリクエストヘッダを設定します |
respond(Number status, Object headerDef, String body) | Void | ステータス、レスポンスヘッダ、レスポンスボディを設定します |
※実際の動作を確認したところ、FakeXHRにresponseXML/autoRespondAfter()/autoRespondが定義されていなかったため、API一覧から除外しています。
Fake Server
FakeXMLHttpRequestインスタンスを操作するための高レベルAPIです。
API
var server = sinon.fakeServer.create()
Fake Serverインスタンスを生成します。このAPIは内部でsinon.useFakeXMLHttpRequest()を実行します。
書き換えられたXHRを元に戻す場合は、server.restore()を実行して下さい。
var server = sinon.fakeServerWithClock.create()
タイマー(時刻)を詐称する機能を持つFake Serverインスタンスを生成します。
書き換えられたXHRを元に戻す場合は、server.restore()を実行して下さい。
server.respondWith(String|Array|Function response)
指定されたURLで実行されたAjaxに対するレスポンスを設定します。
デフォルトは
- ステータスコード: 404
- レスポンスヘッダ: {}
- レスポンスボディ: ""
を返すよう設定されています。
このメソッドのパラメータには、以下の3通りの指定ができます。
- レスポンスボディ文字列
- ステータスコード、レスポンスヘッダ、レスポンスボディの順で値を持つ配列
- 関数
server.respondWith(String url, String|Array|Function response)
第一引数のURLでAjaxで呼び出された場合に返すレスポンスを設定します。
server.respondWith(String method, String url, String|Array|Function response)
第一引数のメソッド(GET,POST,PUT,DELETE)と第二引数のURLでAjaxで呼び出された場合に返すレスポンスを設定します。
server.respondWith(RegExp urlRegExp, String|Array|Function response)
第一引数の正規表現に一致するURLでAjaxで呼び出された場合に返すレスポンスを設定します。
server.respondWith(String method, RegExp urlRegExp, String|Array|Function response)
第一引数のメソッド(GET,POST,PUT,DELETE)と、第二引数の正規表現に一致するURLでAjaxで呼び出された場合に返すレスポンスを設定します。
server.respond()
respondWith()で設定した条件に一致する呼び出しに対して、非同期でレスポンスを返します。
そのため、respond()を実行するよりも前にrespondWith()に値を設定する必要があります。
server.autoRespond
trueを設定した場合、respond()を実行しなくても自動でrespondWith()の条件に一致する呼び出しに対してレスポンスを返します。
server.autoRespondAfter
呼び出しが行われてから何ms後にレスポンスを返すか時間(ミリ秒)を指定します。
server.autoRespondがtrueの場合のみ有効になります。
server.fakeHTTPMethods
trueを設定した場合、server.getHTTPMethod()の引数に指定されたリクエストボディから_methodを探してそのパラメータに指定されているメソッドが実際の通信で使用するメソッドとして判定します。
server.getHTTPMethod(Object request)
引数に指定されたリクエストオブジェクトから、HTTPメソッドを決定するために使用される内部関数。
server.restore()
sinon.fakeServer.create() または sinon.fakeServerWithClock.create() の実行によって書き換えられたXHRクラスを、元の状態(ネイティブ)に戻します。
Assertion
Assertionは、SpyとStubが持つ情報を検証するための機能を提供します。
以下のコードは、spyオブジェクトが1回実行されたかをアサートしています。
function now(fn) {
fn(+new Date());
}
now(spy);
sinon.assert.calledOnce(spy);
アサートの結果に誤りがある場合は例外が発生します。
例えば、sinon.assert.calledOnce()の場合は、デフォルトで以下のメッセージが表示されます。
API
名前 | 戻り値 | 説明 |
---|---|---|
sinon.assert.fail(message) | void | 引数のメッセージを保持する、sinon.assert.failExceptionで指定されたエラークラスをスローします |
sinon.assert.failException | 〃 | Assersion APIがスローするデフォルトのエラークラス(デフォルトはAssertError) |
sinon.assert.pass(assertion) | 〃 | アサートが通過するごとに実行されるメソッドを定義します |
sinon.assert.notCalled(spy) | 〃 | 引数のSpyが一度も呼び出されていないかチェックします |
sinon.assert.called(spy) | 〃 | 引数のSpyが一度も呼び出されていないか検証します |
sinon.assert.calledOnce(spy) | 〃 | 引数のSpyが1度実行されたかを検証します |
sinon.assert.calledTwice() | 〃 | 引数のSpyが2度実行されたかを検証します |
sinon.assert.calledThrice() | 〃 | 引数のSpyが3度実行されたかを検証します |
sinon.assert.callCount(spy, num) | 〃 | 引数のSpyが第二引数numの回数分実行されたかを検証します |
sinon.assert.callOrder(spy1, spy2, ...) | 〃 | 引数で指定した順番でSpyが実行されたかを検証します |
sinon.assert.calledOn(spy, obj) | 〃 | Spyが実行されたときのコンテキスト(this)が、第二引数のobjであるかを検証します |
sinon.assert.alwaysCalledOn(spy, obj) | 〃 | 全ての実行において、実行されたときのコンテキスト(this)が第二引数のobjであるかを検証します |
sinon.assert.calledWith(spy, arg1, arg2, ...) | 〃 | 第二引数以降に指定された値と同じ引数でSpyが実行されたか(部分一致)を検証します |
sinon.assert.alwaysCalledWith(spy, arg1, arg2, ...) | 〃 | 全ての実行において、第二引数以降に指定された値と同じ引数でSpyが実行されたか(部分一致)を検証します |
sinon.assert.neverCalledWith(spy, arg1, arg2, ...) | 〃 | 全ての実行において、第二引数以降に指定された値と異なる引数でSpyが実行されたかを検証します |
sinon.assert.calledWithExactly(spy, arg1, arg2, ...) | 〃 | 第二引数以降に指定された値と同じ引数でSpyが実行されたか(完全一致)を検証します |
sinon.assert.alwaysCalledWithExactly(spy, arg1, arg2, ...) | 〃 | 全ての実行において、第二引数以降に指定された値と同じ引数でSpyが実行されたか(完全一致)を検証します |
sinon.assert.calledWithMatch(spy, arg1, arg2, ...) | 〃 | 引数ごとにsinon.match()でマッチングを行います。このメソッドは sinon.assert.calledWith(spy, sinon.match(arg1), sinon.match(arg2), ...) と同義です |
sinon.assert.alwaysCalledWithMatch(spy, arg1, arg2, ...) | 〃 | 全ての実行において、引数ごとにsinon.match()でマッチングを行います。このメソッドは sinon.assert.alwaysCalledWith(spy, sinon.match(arg1), sinon.match(arg2), ...) と同義です |
sinon.assert.neverCalledWithMatch(spy, arg1, arg2, ...) | 〃 | 引数ごとにsinon.match()でマッチングを行い、全て一致しないことを検証します。 |
sinon.assert.threw(spy, exception) | 〃 | spyの実行で第二引数のexceptionと同じ型の例外が発生したかを検証します |
sinon.assert.alwaysThrew(spy, exception) | 〃 | 全てのspyの実行で、第二引数のexceptionと同じ型の例外が発生したかを検証します |
sinon.assert.expose(object, options) | 〃 | 第一引数objectに指定したオブジェクトに、Assert APIを公開します。第二引数のoptionsには2つのプロパティを指定できます。1つ目はprefixで、公開されるアサーションメソッドの接頭辞に付与したい文字列をこのプロパティに指定します。2つ目はincludeFailで、trueをこのプロパティに指定すると、failとfailExceptionも一緒に公開します |
sinon.assert.calledWith()とsinon.assert.calledWithExactly()の違い
calledWith()は、Spyを実行したときに指定された引数と部分一致すればアサートが通りますが、
calledWithExactly()の場合は完全に引数が一致している必要があります。
以下のコードは、calledWith()の実行により部分一致でアサートがパスすることを確認できます
spy(10, 11, 12, 13);
sinon.assert.calledWithExactly(spy, 10, 11, 12); // パスするので例外は発生しない
以下のコードは、calledWithExactly()の実行により完全一致でないとアサートがパスしないことを確認できます
spy(10, 11, 12, 13);
sinon.assert.calledWithExactly(spy, 10, 11, 12); // 第四引数の13が一致していないので、例外がスローされる
Matcher
Matcherはsinon.assertと同様に、spy.returned、spy.calledWithへの引数として渡すことができます。 Matcherは曖昧または厳密に判定をおこなうことができます。
以下のコードは、メソッドがどのような引数で実行されたかをMatcherを使用してアサートしています。(※1)
pages: 42,
author: "cjno"
};
var spy = sinon.spy();
spy(book);
sinon.assert.calledWith(spy, sinon.match({
author: "cjno"
}));
sinon.assert.calledWith(spy, sinon.match.has("pages", 42));
calledWithでmatcherに指定した期待値とspyの結果が異なる場合、以下のような例外が発生します。
以下の例外は、sinon.match.has()でpagesの期待値を42から41に変更した場合の結果です。
spy({ author: "cjno", pages: 42 })
API
名前 | 戻り値 | 説明 |
---|---|---|
sinon.match(number) | Matcher | 数値を等価比較するMatcherを生成します |
sinon.match(string) | 〃 | 文字列を部分一致で比較するMatcherを生成します |
sinon.match(regexp) | 〃 | 正規表現に一致するMatcherを生成します |
sinon.match(object) | 〃 | オブジェクトの構造に部分的または完全に一致することを検証するMatcherを生成します。引数の値は比較するオブジェクトと部分または完全に同じプロパティを持っていることと、nullまたはundefinedではない必要があります |
sinon.match(function) | 〃 | カスタムMatcherを生成します |
sinon.match.any | 〃 | 値が定義されていないことを検証するMatcherを生成します |
sinon.match.defined | 〃 | 値が定義されていることを検証するMatcherを生成します |
sinon.match.truthy | 〃 | 値がtrueであることを検証するMatcherを生成します。但し"1"、1とった値でもtrueと判定されるため注意 |
sinon.match.falsy | 〃 | 値がfalseであることを検証するMatcherを生成します。但し""、0とった値でもfalseと判定されるため注意 |
sinon.match.bool | 〃 | 値が真偽値(true/false)であることを検証するMatcherを生成します |
sinon.match.number | 〃 | 値が数値型であることを検証するMatcherを生成します |
sinon.match.string | 〃 | 値が文字列であることを検証するMatcherを生成します |
sinon.match.object | 〃 | 値がオブジェクトであることを検証するMatcherを生成します |
sinon.match.func | 〃 | 値がメソッドであることを検証するMatcherを生成します |
sinon.match.array | 〃 | 値が配列であることを検証するMatcherを生成します |
sinon.match.regexp | 〃 | 値が正規表現であることを検証するMatcherを生成します |
sinon.match.date | 〃 | 値が日付であることを検証するMatcherを生成します |
sinon.match.same(ref) | 〃 | 比較する値と引数の値を厳密比較で一致することを検証するMatcherを生成します |
sinon.match.typeOf(type) | 〃 | 比較する値が引数に指定した型であるかを検証するMatcherを生成します |
sinon.match.instanceOf(type) | 〃 | 比較する値が引数に指定した型のインスタンスであるかを検証するMatcherを生成します |
sinon.match.has(property[, expectation]) | 〃 | 比較する値が指定したプロパティを定義しているかを検証するMatcherを生成します |
sinon.match.hasOwn(property[, expectation]) | 〃 | sinon.match.hasと検証内容は同じですが、プロパティが自分自身に定義がいる必要があり、継承されたプロパティは無視されます。 |
条件を組み合わせて使用する
全てのMatcherAPIはor()とand()を実装しています。
この2つのメソッドを使用することで、複数の条件を指定したMatcherを作成することができます。
以下のコードは、※1のコードをand()を使用して書き換えたものです。
pages: 42,
author: "cjno"
};
var spy = sinon.spy();
spy(book);
var combinationMatcher = sinon.match({author: "cjno"}).and(sinon.match.has("pages", 42));
sinon.assert.calledWith(spy, combinationMatcher);
カスタムMatcherを作成する
sinon.match() にメソッドとエラーメッセージを指定することで、独自のMatcherを作成することができます。
以下のコードは、※1のコードをカスタムMatcherで書き換えたものです。
pages: 42,
author: "cjno"
};
var spy = sinon.spy();
spy(book);
sinon.assert.calledWith(spy, sinon.match({
author: "cjno"
}));
var customMatcher = sinon.match(function (value) {
value.pages === 42 && value .author === "cjno"
}, "値が不正です");
sinon.assert.calledWith(spy, trueIsh);
Sandbox
Sandboxを使用すると、restoreとverifyの呼び出しが簡略化されます。
また、グローバルにアクセス可能なfakeXHR、fakeTimerやStubを使用している場合は、Sandboxを使用することでクリーンアップが容易になります。
API
var sandbox = sinon.sandbox.create()
Sandboxオブジェクトを生成します。
var sandbox = sinon.sandbox.create(config)
引数に指定した設定情報に従って、Sandboxオブジェクトを生成します。
デフォルトの設定値
injectInto: null,
properties: ["spy", "stub", "mock", "clock", "server", "requests"],
useFakeTimers: true,
useFakeServer: true
}
各設定値の説明
プロパティ名 | 説明 |
---|---|
injectInto | propertiesで指定された機能を、このプロパティに指定したオブジェクトに公開します |
properties | どの機能をsandboxで有効にするか、機能を表す文字列(spy/stub/mock/clock/server/requests)を持つ配列で指定します。 |
useFakeTimers | trueを設定すると、clockというプロパティ名でFakeTimer APIを公開します。 |
useFakeServer | trueを設定すると、serverとrequestsというプロパティ名でFakeServer APIを公開します |
sandbox.spy()
sandbox.restore()で復元可能な、Spyオブジェクトを生成します
sandbox.stub()
sandbox.restore()で復元可能な、Stubオブジェクトを生成します
sandbox.mock()
sandbox.restore()で復元可能な、Mockオブジェクトを生成します
sandbox.useFakeTimers()
sandbox.restore()で復元可能な、Fake Timerオブジェオブジェクトを生成します
sandbox.useFakeXMLHttpRequest()
sandbox.restore()で復元可能な、FakeXHRオブジェクトを生成します
sandbox.useFakeServer()
sandbox.restore()で復元可能な、Fake Serverオブジェクトを生成します
sandbox.restore()
各APIを元の状態にもどします
Utility
Sinon.JSにはライブラリや内部で使用されているユーティリティがいくつか存在しますが、以下で説明されていないメソッドはパブリックなAPIではないため、将来変更される可能性があるため注意が必要です。
API
sinon.createStubInstance(Function constructor)
引数に指定したコンストラクタがprototypeに持つメソッドを全てStub化したオブジェクトを返します。
引数に指定したコンストラクタは実行されません。Stubの詳細についてはこちらを参照して下さい。
sinon.format(Object obj)
指定したオブジェクトの構造を文字列に表現します。
inner1: {
inner2: {
func: function() {
alert('hello!');
},
num1: 10,
str1: 'aaa'
}
}
};
sinon.format(obj);
実行結果
sinon.log(String message)
デバッグに役立つ内部エラーを出力します。デフォルトは空のメソッドが設定されているので、必要に応じて設定を変更して下さい。
例.内部エラーをコンソールに出力する場合
console.log(message);
};