Angular 我如何用单元测试涵盖rxjs订阅方法?
我试图编写单元测试来覆盖我的每一行代码。我有两行代码没有涵盖 我不明白我在哪里犯了错误,以及我如何才能覆盖这些代码行 以下是未覆盖代码行的图像: Product-item.spect.tsAngular 我如何用单元测试涵盖rxjs订阅方法?,angular,rxjs,angular-unit-test,Angular,Rxjs,Angular Unit Test,我试图编写单元测试来覆盖我的每一行代码。我有两行代码没有涵盖 我不明白我在哪里犯了错误,以及我如何才能覆盖这些代码行 以下是未覆盖代码行的图像: Product-item.spect.ts 从'@angular/common/http/testing'导入{HttpClientTestingModule}; 从“@angular/core”导入{CUSTOM_ELEMENTS_SCHEMA}”; 从“@angular/core/testing”导入{async,ComponentFixture
从'@angular/common/http/testing'导入{HttpClientTestingModule};
从“@angular/core”导入{CUSTOM_ELEMENTS_SCHEMA}”;
从“@angular/core/testing”导入{async,ComponentFixture,TestBed};
从“@angular/router/testing”导入{RouterTestingModule};
从“../../services/product.service”导入{ProductService};
从“./product item.component”导入{ProdItemComponent};
描述('ProdItemComponent',()=>{
let组件:ProdItemComponent;
let夹具:组件夹具;
让产品服务:产品服务;
让我们来看看这个项目:任何;
beforeach(异步(()=>{
TestBed.configureTestingModule({
声明:[ProductItemComponent],
导入:[HttpClientTestingModule,RouterTestingModule],
提供者:[ProductService],
模式:[自定义元素\u模式]
})
.compileComponents();
}));
在每个之前(()=>{
mockProductItem={
id:“c7336f01-5219-4631-a865-af1fa9837766”,
标题:“地毯”,
描述:“柔软的地毯”
}
fixture=TestBed.createComponent(ProductItemComponent);
组件=fixture.componentInstance;
productService=TestBed.inject(productService);
fixture.detectChanges();
component.productItem=mockProductItem;
component.selectedItemId=component.mockProductItem.id;
});
它('应该创建',()=>{
expect(component.toBeTruthy();
});
它('应该调用delete方法',()=>{
component.onDelete();
fixture.detectChanges();
productService.deleteProduct(component.selectedItemId).subscribe(selectedItemId=>{
expect(selectedItemId.toBeTruthy();
const spy=spyOn(component.fetchDataEventEmitter,'emit');
期望(间谍)。已被调用();
})
});
expect(component.displayConfirmDialog).toBe(false);
});
产品服务
deleteProduct(productId:string){
返回this.httpClient.delete(
此.BASE\u URL+
这是一个.DELETE\u项目\u URL(
产品ID
)
)
}
产品组件
onDelete():void{
如果(此.selectedItemId){
this.productService.deleteProduct(this.selectedItemId).subscribe(res=>{
this.fetchDataEventEmitter.emit();
});
}
this.displayConfirmDialog=false;
}
看起来您在执行过程中创建间谍对象的时间太晚了。如果您在调用productService.delete之前创建了spy对象,但将expect断言保留在原来的位置,则应该可以解决此问题。尝试为fetchDataEventEmitter
属性分配一个简单的可观察对象,并将其移到案例顶部:
it('should call delete method', () => {
component.fetchDataEventEmitter = of({})
component.onDelete();
fixture.detectChanges();
productService.deleteProduct(component.selectedItemId).subscribe(selectedItemId => {
expect(selectedItemId).toBeTruthy();
})
});
最后一个
expect
此处不合适,应上移一行
it('should call delete method', () => {
component.onDelete();
fixture.detectChanges();
productService.deleteProduct(component.selectedItemId).subscribe(selectedItemId => {
expect(selectedItemId).toBeTruthy();
const spy = spyOn(component.fetchDataEventEmitter, 'emit');
expect(spy).toHaveBeenCalled();
});
// should go here
expect(component.displayConfirmDialog).toBe(false);
});
// expect(component.displayConfirmDialog).toBe(false);
您需要使用spyObject模拟ProductService
,因为您不想在单元测试中执行实际的http
调用
let component: ProdItemComponent;
let fixture: ComponentFixture<ProdItemComponent>;
let productService: ProductService;
let mockProductItem: any;
// add this line
let mockProductService: jasmine.SpyObj<ProductService>;
beforeEach(async(() => {
// create a spy object
// the first string is an identifier and is optional. The array of strings
// are the public methods that you would like to mock.
mockProductService = jasmine.createSpyObj<ProductService>('ProductService', ['deleteProduct']);
TestBed.configureTestingModule({
declarations: [ProductItemComponent],
// get rid of HttpClientTestingModule since we are mocking
// ProductService now
imports: [/*HttpClientTestingModule*/, RouterTestingModule],
// when the component asks for ProductService, give the mocked one
providers: [{ provide: ProductService, useValue: mockProductService }],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
.compileComponents();
}));
...
it('should call delete method', () => {
// make the deleteProduct method return an observable of empty string
mockProductService.deleteProduct.and.returnValue(of(''));
// spy on the emission
const emitSpy = spyOn(component.fetchDataEventEmitter, 'emit');
component.onDelete();
fixture.detectChanges();
expect(emitSpy).toHaveBeenCalled();
expect(component.displayConfirmDialog).toBeFalse();
});
let组件:ProdItemComponent;
let夹具:组件夹具;
让产品服务:产品服务;
让我们来看看这个项目:任何;
//添加这一行
让mockProductService:jasmine.SpyObj;
beforeach(异步(()=>{
//创建一个间谍对象
//第一个字符串是标识符,是可选的
//是您想要嘲笑的公共方法。
mockProductService=jasmine.createSpyObj('ProductService',['deleteProduct']);
TestBed.configureTestingModule({
声明:[ProductItemComponent],
//摆脱HttpClientTestingModule,因为我们正在模拟
//立即提供产品服务
导入:[/*HttpClientTestingModule*/,RouterTestingModule],
//当组件请求ProductService时,给出模拟的一个
提供程序:[{提供:ProductService,useValue:mockProductService}],
模式:[自定义元素\u模式]
})
.compileComponents();
}));
...
它('应该调用delete方法',()=>{
//使deleteProduct方法返回一个可观察的空字符串
mockProductService.deleteProduct.and.returnValue(of(“”));
//监视发射
const emitSpy=spyOn(component.fetchDataEventEmitter,'emit');
component.onDelete();
fixture.detectChanges();
expect(emitSpy).tohavebeincall();
expect(component.displayConfirmDialog.toBeFalse();
});
我将这个“const spy=spyOn(component.fetchDataEventEmitter,'emit')移到了顶部,但是这些代码行是相同的,它仍然没有被覆盖。SPEC没有期望应该调用delete Method我在尝试为fetchDataEventEmitter分配一个简单的可观察对象时遇到了这个错误类型“Observable”缺少类型“EventEmitter”中的以下属性:emit、observators、closed、isStopped和其他7个属性。DoestspyOn(component.fetchDataEventEmitter,“emit”)代码>不行?好像不行。谢谢。现在,我将传递一行未包含的代码。