web-dev-qa-db-ja.com

単体テストAngular 2サービス対象

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'から他のものに変更した場合、テストは常にイベントに合格します。

すべてをasyncfakeAsyncでラップすることも試みましたが、結果は同じです。

callNextOnSubjectserviceSubjectProperty$サブジェクトにデータを送信しているかどうかをテストする正しい方法は何ですか?

7
crdevdeu

解決策を探しているときに私はこの記事を見つけました:

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'サブスクリプションの前に、そのイベントを「キャッチ」するものはありません。

9
pbialy

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
});
1
mth khaled

サブジェクトが呼び出された後、コンポーネントで変更されたデータをテストする必要があります。プライベート変数または保護された変数ではなく、パブリック変数のみをテストする必要があります。例えば:

サービス:

@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);
        });
    });
});
1
Pasha Sybiriak