簡體   English   中英

單元測試 Angular 2 服務主題

[英]Unit test Angular 2 service subject

我正在嘗試為一個 angular 服務編寫一個測試,該服務具有一個 Subject 屬性和一個在該主題上調用.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包裝所有東西,但結果是一樣的。

測試callNextOnSubject是否向serviceSubjectProperty$ Subject 發送數據的正確方法是什么?

我在搜索解決方案時發現了這篇文章:

http://www.syntaxsuccess.com/viewarticle/unit-testing-eventemitter-in-angular-2.0

它對我來說效果很好(它很短,不要害怕打開它)。

我在這里粘貼它,所以它可能會幫助那些來到這個網站尋找答案的人。


關於提出的問題 - 我認為你需要改變:

  subjectService.callNextOnSubject('test');

  subjectServiceProperty$.subscribe((message) => {
    expect(message).toBe('test');
  })

  subjectServiceProperty$.subscribe((message) => {
    expect(message).toBe('test');
  })

  subjectService.callNextOnSubject('test');

,所以先訂閱,然后發出一個事件。

如果您在訂閱之前發出'test' ,那么什么都不會“捕獲”該事件。

在調用主題后,您應該測試組件中更改的數據。 應該只測試公共變量,而不是私有或受保護; 例如:

服務:

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

到目前為止,使用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
});

subscribe 必須在前面,然后調用方法

it(`#${YourCompoent.prototype.yourMethod.name} subscribe must come before, and then call method`, fakeAsync( () => {
    yourServiceSubject.filter$.subscribe(ev => {
      expect(ev).toEqual(mock.mockFilterDefault())
    });
    component.sendFilterForm();
  }));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM