Jasmineで非同期のリクエスト終了後にテストを実行する

今日はJasmineを使ってBackbone.Viewのテストを書いていました。
サンプルに載っていた通り、非同期リクエストでViewのテンプレートを読み込んでいたのですが、テンプレートの読み込みが終了した時点でテストを実行しようとして、うまくいかずにハマりました。Jasmineを使った非同期リクエストのテストについて調べて「waitsFor」と「runs」を使うことで、思い通りに実行できました。

waitsFor(function, message, timeout)
https://github.com/pivotal/jasmine/wiki/Asynchronous-specs
waitsForを使うとtimeoutで指定した秒数(ミリ)が経過するまで、引数に渡したfunctionからtrueが返ってくるのを待ってくれます。
もしtrueが返ってくるまえにtimeoutに達した場合はmessageで指定したエラーメッセージが戻ってきます。

下の例では、テンプレートを非同期で読み込んで、読み込みが完了したらloadedがtrueになります。
waitsForで500ミリ秒間、loadedの値がtrueになるのを待ってから、次のrunsを実行しています。

beforeEachの時点でviewを用意しているので、itが実行されるときにはテンプレートの読み込みが終わって、viewの準備ができた状態になっています。

describe("nice test", function(){
	beforeEach(function(){
		var self = this;
		this.loaded = false;
		this.model = new Backbone.Model();
		
		templateLoader.load(["nice-template"], function(){
			self.loaded = true;
		});	
		
		waitsFor(function(){
			return self.loaded;
		}, "template loading timed out", 500);
		
		runs(function(){
			self.view = new MyView({model: self.model});
		});
	}
	
	it("should be testing the view", function(){
		expect($(this.view.render().el).html()).contains("hoge");
	});
});

Source:
http://pivotal.github.com/jasmine/
https://github.com/pivotal/jasmine/wiki/Asynchronous-specs
http://d.hatena.ne.jp/hagino_3000/20111009/jasmine