2つのステートフルサービスshop
とschedule
に依存するサービスwarehouse
があるとします。ユニットテストのためにschedule
とwarehose
の異なるバージョンをshop
に挿入するにはどうすればよいですか?
私のサービスは次のとおりです。
angular.module('myModule').service('shop', function(schedule, warehouse) {
return {
canSellSweets : function(numRequiredSweets){
return schedule.isShopOpen()
&& (warehouse.numAvailableSweets() > numRequiredSweets);
}
}
});
ここに私のモックがあります:
var mockSchedule = {
isShopOpen : function() {return true}
}
var mockWarehouse = {
numAvailableSweets: function(){return 10};
}
私のテストは次のとおりです。
expect(shop.canSellSweets(5)).toBe(true);
expect(shop.canSellSweets(20)).toBe(false);
beforeEach(function () {
module(function ($provide) {
$provide.value('schedule', mockSchedule);
});
});
モジュールは、angular-mocksモジュールによって提供される関数です。文字列引数を渡すと、対応する名前のモジュールがロードされ、すべてのプロバイダー、コントローラー、サービスなどが仕様に使用できます。通常、それらは注入機能を使用してロードされます。コールバック関数を渡すと、Angularの$ injectorサービスを使用して呼び出されます。次に、このサービスはコールバック関数に渡された引数を見て、どの依存関係をコールバックに渡す必要があるかを推測しようとします。
Atillaの答えを改善し、KevSheedyのコメントに直接答えて、module('myApplicationModule')
のコンテキストで次のことを行います。
beforeEach(module('myApplicationModule', function ($provide) {
$provide.value('schedule', mockSchedule);
}));
CoffeeScriptではいくつかの問題が発生するため、最後にnullを使用します。
beforeEach ->
module ($provide) ->
$provide.value 'someService',
mockyStuff:
value : 'AWESOME'
null
詳細はこちらをご覧ください
https://docs.angularjs.org/guide/services#unit-testing
$ provideサービスを利用したい場合。あなたの場合
$provide.value('schedule', mockSchedule);
ジャスミンを使用している場合、ジャスミンのスパイで呼び出しをモックする別の方法があります( https://jasmine.github.io/2.0/introduction.html#section-Spies )。
これらを使用すると、関数呼び出しの対象となり、必要に応じて元のオブジェクトへの呼び出しを許可できます。テストファイルの先頭が$ provideとモックの実装で詰まるのを防ぎます。
あなたのテストの前に、私は次のようなものを持っています:
var mySchedule, myWarehouse;
beforeEach(inject(function(schedule, warehouse) {
mySchedule = schedule;
myWarehouse = warehouse;
spyOn(mySchedule, 'isShopOpen').and.callFake(function() {
return true;
});
spyOn(myWarehouse, 'numAvailableSweets').and.callFake(function() {
return 10;
});
}));
また、これは$ provideメカニズムと同様の方法で動作するはずです。スパイする注入された変数のローカルインスタンスを提供する必要があることに注意してください。
私は最近、AngularJSでのモックテストを簡単にするngImprovedTestingモジュールをリリースしました。
あなたの例では、ジャスミンテストで交換するだけで済みます...
beforeEach(module('myModule'));
...と...
beforeEach(ModuleBuilder.forModule('myModule').serviceWithMocks('shop').build());
NgImprovedTestingの詳細については、紹介ブログ投稿をご覧ください: http://blog.jdriven.com/2014/07/ng-improved-testing-mock-testing-for-angularjs-made-easy/ =
このようにモジュールにモックを置く方が簡単です:
beforeEach(function () {
module('myApp');
module({
schedule: mockSchedule,
warehouse: mockWarehouse
}
});
});
インジェクションを使用して、テスト前の操作のためにこれらのモックへの参照を取得できます。
var mockSchedule;
var mockWarehouse;
beforeEach(inject(function (_schedule_, _warehouse_) {
mockSchedule = _schedule_;
mockWarehouse = _warehouse_;
}));
私の答えがそれほど役に立たないことを願っていますが、$provide.service
beforeEach(() => {
angular.mock.module(
'yourModule',
($provide) => {
$provide.service('yourService', function() {
return something;
});
}
);
});