单元测试Angular2个服务对象
Unit test Angular 2 service subject
我正在尝试为 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$
主题发送数据的正确方法是什么?
你应该测试调用你的主题后组件中发生变化的数据。应该只测试 public 个变量,而不是私有或受保护的;
例如:
服务:
@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);
});
});
});
我在搜索解决方案时找到了这篇文章:
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'
,则不会 "catch" 该事件。
到目前为止,使用 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();
}));
我正在尝试为 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$
主题发送数据的正确方法是什么?
你应该测试调用你的主题后组件中发生变化的数据。应该只测试 public 个变量,而不是私有或受保护的; 例如:
服务:
@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);
});
});
});
我在搜索解决方案时找到了这篇文章:
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'
,则不会 "catch" 该事件。
到目前为止,使用 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();
}));