angularサービスのサブジェクトプロパティと、そのサブジェクトに対して.next()
を呼び出すメソッドを含む)のテストを記述しようとしています。
サービスは次のとおりです。
@Injectable()
export class SubjectService {
serviceSubjectProperty$: Subject<any> = new Subject();
callNextOnSubject(data: any) {
this.serviceSubjectProperty$.next(data);
}
}
そしてそのサービスのテストファイル:
import { TestBed, inject } from '@angular/core/testing';
import { SubjectService } from './subject.service';
describe('SubjectService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
SubjectService
]
});
});
it('callNextOnSubject() should emit data to serviceSubjectProperty$ Subject',
inject([SubjectService], (subjectService) => {
subjectService.callNextOnSubject('test');
subjectServiceProperty$.subscribe((message) => {
expect(message).toBe('test');
})
}));
});
subjectService.callNextOnSubject
の引数を'test'
から他のものに変更した場合、テストは常にイベントに合格します。
すべてをasync
とfakeAsync
でラップすることも試みましたが、結果は同じです。
callNextOnSubject
がserviceSubjectProperty$
サブジェクトにデータを送信しているかどうかをテストする正しい方法は何ですか?
解決策を探しているときに私はこの記事を見つけました:
http://www.syntaxsuccess.com/viewarticle/unit-testing-eventemitter-in-angular-2.
そしてそれは私にとってはうまくいきました(それは非常に短く、それを開くことを恐れないでください)。
ここに貼り付けているので、このサイトに来て回答を探している人に役立つかもしれません。
質問について-変更する必要があると思います:
subjectService.callNextOnSubject('test');
subjectServiceProperty$.subscribe((message) => {
expect(message).toBe('test');
})
に
subjectServiceProperty$.subscribe((message) => {
expect(message).toBe('test');
})
subjectService.callNextOnSubject('test');
なので、最初にサブスクライブしてから、イベントを発行します。
'test'
サブスクリプションの前に、そのイベントを「キャッチ」するものはありません。
Jasmine 'done'コールバックを使用すると、これまでのところトリックが実行されます。以下のドキュメントを確認してください。 https://jasmine.github.io/api/Edge/global (implementationCallback(doneopt)を参照)
あなたのテストケースを使用した例の下:
it('callNextOnSubject() should emit data to serviceSubjectProperty$ Subject', (done) => {
inject([SubjectService], (subjectService) => {
subjectService.callNextOnSubject('test');
subjectServiceProperty$.subscribe((message) => {
expect(message).toBe('test');
done();
})
}) // function returned by 'inject' has to be invoked
});
サブジェクトが呼び出された後、コンポーネントで変更されたデータをテストする必要があります。プライベート変数または保護された変数ではなく、パブリック変数のみをテストする必要があります。例えば:
サービス:
@Injectable()
export class SomeService {
onSomeSubject: Subject<any> = new Subject();
someSubject(string: string) {
this.onSomeSubject.next(string);
}
}
成分:
export class SomeComponent {
@Input() string: string;
constructor(private service: SomeService) {
service.onSomeSubject.subscribe((string: string) => {
this.string = string;
}); //don't forget to add unsubscribe.
}
}
テスト:
...
describe('SomeService', () => {
let someService: SomeService; // import SomeService on top
let someComponent: SomeComponent; // import SomeService on top
beforeEach(() => {
TestBed.configureTestingModule({
providers: [SomeService, SomeComponent]
});
injector = getTestBed();
someService = injector.get(SomeService);
someComponent = injector.get(SomeComponent);
});
describe('someSubject', () => {
const string = 'someString';
it('should change string in component', () => {
someService.someSubject(string);
expect(someComponent.string).tobe(string);
});
});
});