angular 如何涵盖 RxJS 主题的 Jasmine 单元测试
How to cover Jasmine unit test for RxJS subject in angular
我很新的茉莉花单元测试用例。我的场景可能很简单,但我不确定如何涵盖以下 class 的 ngInit 测试用例。有人可以帮助我吗,
export class Component1 implements OnInit {
details$: Observable<any>;
name: string;
error: string
constructor(private service1: Service1, private service2: Service2) { }
ngOnInit() {
this.service1.service1Subject.subscribe( info => {
if(info['url']){
this.details$ = this.service2.get(info['url'])
this.details$.subscribe(
(info) => { this.name = info['name']};
(error) => { this.erro = error['error']};
);
}
});
}
}
测试用例:
describe('Component1', () => {
let component: Component1;
let fixture: ComponentFixture<Component1>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [Component1],
imports: [
HttpClientTestingModule, CommonModule
],
providers: [Service1, Service2]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(Component1);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should call Get Data', () => {
const service2: Service2 = TestBed.get(Service2);
const spy = jest.spyOn(service2, 'get').mockImplementation(() => {
return {
info : [...],
name : ''
}
});
component.ngOnInit();
expect(spy).toHaveBeenCalled();
});
});
这里的问题是,我不确定如何模拟 service1,RxJS 主题。请有人帮助我。
我看到您正在使用 Jest,但这是我设置组件测试的方式,该组件测试使用公开 Subject
.
的服务
- 为您的所有服务创建模拟
- 在您的测试模块中提供它们
- 用于控制数据流的模拟实现
执行你的断言
describe('Component1', () => {
let component: Component1;
let fixture: ComponentFixture<Component1>;
//create mock service objects
let service1Mock = jasmine.createSpyObj('service1', ['toString']);
let service2Mock = jasmine.createSpyObj('service2', ['get']);
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [Component1],
imports: [
HttpClientTestingModule,
CommonModule
],
providers: [
//Set up the dependency injector, but use the mocks as the implementation
{ provide: Service1, useValue: service1Mock },
{ provide: Service2, useValue: service2Mock }
]
}).compileComponents();
}));
beforeEach(() => {
//add an observable to your service
//this will also help reset the observable between each test
service1Mock.service1Subject = new Subject<any>();
});
beforeEach(() => {
fixture = TestBed.createComponent(Component1);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should get the data', () => {
//configure the mock implementation of "service2.get" to successfully return data
//You can alternatively use "throw({error: 'some_error'})" to test your "error" case
service2Mock.get.and.returnValue(of({name: 'some_name'}));
//tell the mock to emit some data!
service1Mock.service1Subject.next( {url: 'some_url'} );
//Your component subcriptions should handle the event, perform whatever test needs to do
});
});
我知道 Jasmine 计划让 create spy objects with attributes 成为可能,但我自己并没有真正使用过它。
顺便说一句,如果您不在模板中使用 details$
,则可以完全删除该变量。
ngOnInit(){
this.service1.service1Subject.subscribe( info => {
if(info['url']){
this.service2.get(info['url']).subscribe(
(info) => { this.name = info['name']};
(error) => { this.error = error['error']};
);
}
});
}
先模拟主题,然后将其添加到模拟服务。
describe('Component1', () => {
let component: Component1;
let fixture: ComponentFixture<Component1>;
let mockSubject = new Subject<boolean>();
mockSubject.next(true);
let mockService = jasmine.createSpyObj(Service, ['getTheme']);
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [Component1],
providers: [{ provide: Service, useValue: mockService }],
}).compileComponents();
mockService.getTheme.and.returnValue(false);
mockService.theme$ = mockSubject; <---- assign mocked value
fixture = TestBed.createComponent(Component1);
component = fixture.componentInstance;
fixture.detectChanges();
});
})
我很新的茉莉花单元测试用例。我的场景可能很简单,但我不确定如何涵盖以下 class 的 ngInit 测试用例。有人可以帮助我吗,
export class Component1 implements OnInit {
details$: Observable<any>;
name: string;
error: string
constructor(private service1: Service1, private service2: Service2) { }
ngOnInit() {
this.service1.service1Subject.subscribe( info => {
if(info['url']){
this.details$ = this.service2.get(info['url'])
this.details$.subscribe(
(info) => { this.name = info['name']};
(error) => { this.erro = error['error']};
);
}
});
}
}
测试用例:
describe('Component1', () => {
let component: Component1;
let fixture: ComponentFixture<Component1>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [Component1],
imports: [
HttpClientTestingModule, CommonModule
],
providers: [Service1, Service2]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(Component1);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should call Get Data', () => {
const service2: Service2 = TestBed.get(Service2);
const spy = jest.spyOn(service2, 'get').mockImplementation(() => {
return {
info : [...],
name : ''
}
});
component.ngOnInit();
expect(spy).toHaveBeenCalled();
});
});
这里的问题是,我不确定如何模拟 service1,RxJS 主题。请有人帮助我。
我看到您正在使用 Jest,但这是我设置组件测试的方式,该组件测试使用公开 Subject
.
- 为您的所有服务创建模拟
- 在您的测试模块中提供它们
- 用于控制数据流的模拟实现
执行你的断言
describe('Component1', () => { let component: Component1; let fixture: ComponentFixture<Component1>; //create mock service objects let service1Mock = jasmine.createSpyObj('service1', ['toString']); let service2Mock = jasmine.createSpyObj('service2', ['get']); beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [Component1], imports: [ HttpClientTestingModule, CommonModule ], providers: [ //Set up the dependency injector, but use the mocks as the implementation { provide: Service1, useValue: service1Mock }, { provide: Service2, useValue: service2Mock } ] }).compileComponents(); })); beforeEach(() => { //add an observable to your service //this will also help reset the observable between each test service1Mock.service1Subject = new Subject<any>(); }); beforeEach(() => { fixture = TestBed.createComponent(Component1); component = fixture.componentInstance; fixture.detectChanges(); }); it('should get the data', () => { //configure the mock implementation of "service2.get" to successfully return data //You can alternatively use "throw({error: 'some_error'})" to test your "error" case service2Mock.get.and.returnValue(of({name: 'some_name'})); //tell the mock to emit some data! service1Mock.service1Subject.next( {url: 'some_url'} ); //Your component subcriptions should handle the event, perform whatever test needs to do }); });
我知道 Jasmine 计划让 create spy objects with attributes 成为可能,但我自己并没有真正使用过它。
顺便说一句,如果您不在模板中使用 details$
,则可以完全删除该变量。
ngOnInit(){
this.service1.service1Subject.subscribe( info => {
if(info['url']){
this.service2.get(info['url']).subscribe(
(info) => { this.name = info['name']};
(error) => { this.error = error['error']};
);
}
});
}
先模拟主题,然后将其添加到模拟服务。
describe('Component1', () => {
let component: Component1;
let fixture: ComponentFixture<Component1>;
let mockSubject = new Subject<boolean>();
mockSubject.next(true);
let mockService = jasmine.createSpyObj(Service, ['getTheme']);
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [Component1],
providers: [{ provide: Service, useValue: mockService }],
}).compileComponents();
mockService.getTheme.and.returnValue(false);
mockService.theme$ = mockSubject; <---- assign mocked value
fixture = TestBed.createComponent(Component1);
component = fixture.componentInstance;
fixture.detectChanges();
});
})