別のサービス(InteractWithServerService)に依存するサービス(ChildService)があります。後者のサービス(InteractWithServerService)は、サーバー呼び出しを行い、「任意の」タイプのオブザーバブルを返すために使用されます。簡単にするために、observableを返すと仮定しましょう。 ChildServiceの単体テストを作成しようとしています。
ChildService
@Injectable()
export class ApplicationService {
constructor(private interactWithServerService:InteractWithServerService){;}
public GetMeData():string {
var output:string;
this.interactWithServerService.get("api/getSomeData").
subscribe(response =>{console.log("server response:", response);
output=response});
return output;
}
}
ServerInteractionService
@Injectable()
export class InteractWithServerService {
constructor(private http: Http) {
;
}
get(url: string): Observable<any> {
return this.http.get(this.url);
}
}
依存サービスをモックすると、テストケースは正常に機能します。すなわち、
class MockInteractWithServerService {
get() {
return Observable.of("some text");
}
}
describe('Service:ChildService', () => {
let childService: ChildService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{ provide: InteractWithServerService, useClass: MockInteractWithServerService },
ChildService],
});
beforeEach(inject([ChildService], (actualService: ChildService) => {
childService= actualService;
}));
fit('should call server-call testCall()', () => {
let actualReturnvalue= childService.GetMeData();
expect(actualReturnvalue).toBe("some text");
});
});
上記の方法は、「n」個の依存関係に対して「n」個の模擬クラスを作成する可能性があるため、好ましくありません。ですから、spyOnを使用して単体テストを作成したいと思います。ただし、テストケースは機能せず、「エラー:Httpのプロバイダーがありません!」がスローされます。エラーが何であるかは理解していますが、依存サービスをスパイしているにもかかわらず、なぜエラーがスローされるのかを知りたいと思います。 「spyOn」が機能していないようです。
describe('Service:ChildService', () => {
let childService: ChildService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
InteractWithServerService,
ChildService],
});
spyOn(InteractWithServerService.prototype, 'get').and
.callFake(()=>
{return Observable.of("some text");});
});
beforeEach(inject([ChildService], (actualService: ChildService) => {
childService= actualService;
}));
fit('should call server-call testCall()', () => {
let actualReturnvalue= childService.GetMeData();
expect(actualReturnvalue).toBe("some text");
});
});
明らかな何かが欠けていますか?
ただし、テストケースは機能せず、「エラー:Httpのプロバイダーがありません!」がスローされます。
まだproviders
にサービスがあるため、Angularはまだ作成しようとしています
providers: [
InteractWithServerService,
ChildService],
モックを作成する代わりにできることclassは、
providers: [
{
provide: InteractWithServerService,
useValue: { get: Observable.of(..) }
}
]
ここでは、任意のオブジェクトを提供するuseValue
を使用しています。それが注入時に使用される値になります。上記の場合、それはあなたのモックメソッドを持つ任意のオブジェクトです。
異なる値を提供できるようにスパイしたい場合は、InteractWithServerService
を挿入してから
spyOn(service, 'get').and.returnValue(Observable.of(...))
// do test
もう1つできることは、ダミーオブジェクトでHttpをモックすることです。
{ provide: Http, useValue: {} }
これでInteractWithServerService
が機能します(現在のようにクラスをプロバイダーに追加するだけです)。そして、あなたはちょうどそれをスパイすることができます
let service = TestBed.get(InteractWithServerService);
spyOn(service, 'get').and.returnValue(..)
// do test
ジャスミング2.6.2の使用:get
は関数なので、上記の答えに矢印関数表記を追加する必要があります。
providers: [
{
provide: InteractWithServerService,
useValue: { get: () => Observable.of(..) }
}
]