单元测试Angular 2服务主题

时间:2017-07-14 20:57:30

标签: angular testing jasmine rxjs subject

我正在尝试为角度服务编写测试,该服务具有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$主题发送数据的正确方法是什么?

3 个答案:

答案 0 :(得分:8)

我在搜索解决方案时发现了这篇文章:

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

它对我来说效果很好(它很短,不要害怕打开它)。

我在这里粘贴它,所以它可能会帮助那些来到这个网站寻找答案的人。

关于提出的问题 - 我认为你需要改变:

string x = Convert.ToString(int.Parse(_dataRx), 2).PadLeft(8, '0');

  subjectService.callNextOnSubject('test');

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

,所以先订阅,然后发出一个事件。

如果您在订阅之前发出 subjectServiceProperty$.subscribe((message) => { expect(message).toBe('test'); }) subjectService.callNextOnSubject('test'); ,那么什么都不会“捕获”该事件。

答案 1 :(得分:1)

在调用主题后,您应该测试组件中更改的数据。应该只测试公共变量,而不是私有或受保护; 例如:

服务:

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

答案 2 :(得分:0)

使用茉莉花&#39;完成&#39;回调将到目前为止,检查下面的文档: 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
});