我有一个注入服务(EntityApi),它扩展了一个类(BaseApi)。在我的规范中,我喜欢用BaseApiStub模拟BaseApi。但这是徒劳的。始终调用EntityApi。
// class
export class BaseApi { // want to mock BaseApi
constructor(injector: Injector) {
console.log("Should not be here...");
}
}
// service
@Injectable()
export class EntityApi extends BaseApi {
constructor(injector: Injector) {
super(injector, "entity");
}
}
// component
@Component({
selector: 'rt-entity-list',
templateUrl: './entity-list.component.html',
})
export class EntityListComponent {
api: any;
constructor(public entityApi: EntityApi) {
this.api = entityApi;
}
}
// mock api
export class BaseApiStub { //mocked api
constructor() {
console.log("You are on track!!")
}
get() { }
}
// spec
describe('EntityListComponent', () => {
let component: EntityListComponent;
let fixture: ComponentFixture<EntityListComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [EntityListComponent],
providers: [ { provide: BaseApi, useClass: BaseApiStub }, // mocked class.
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
beforeEach(() => {
fixture = TestBed.createComponent(EntityListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
预期行为是,在规范中编译组件。它应该调用BaseApiStub,而不是调用BaseApi。我见过如下解决方案。但没有运气。
export class BaseApiStub extends BaseApi { }
测试代码:stackblitz检查控制台。我期待你是 在轨道上!! 记录但收到不应该在这里......
无法进一步发展。有人可以纠正我的错误吗。
答案 0 :(得分:0)
您要做的事情不起作用。依赖注入和类继承没有直接关系。这意味着您无法像这样切换服务的基类。
我认为你有两种方法可以做到这一点。
选项1:
您需要模拟您的EntityApi并在测试中提供此模拟,而不是模拟您的BaseApi并在测试中提供模拟。
选项2:
您可以将BaseApi保留为简单服务并将其作为依赖项提供,而不是让您的EntityApi从BaseApi扩展。
而不是
class EntityApi extends BaseApi {
constructor(private injector: Injector) {
你做了
class EntityApi {
constructor(private api: BaseApi) {
如果您像这样设置EntityApi,它不会从BaseApi扩展,而是将其作为依赖项。然后,您可以创建一个BaseApi的模拟,并像测试中一样提供它。
修改强>
关于你的评论:
因为我应该使用BaseApi中的方法,所以我不能没有延伸。
事实并非如此。假设BaseApi有一个你想要使用的方法foo()。扩展基类时,用法可能如下所示:
class EntityApi extends BaseApi {
constructor(private injector: Injector) {}
exampleMethod() {
this.foo();
}
}
如果你只有依赖关系,你仍然可以调用这样的方法:
class EntityApi {
constructor(private api: BaseApi) {}
exampleMethod() {
this.api.foo();
}
}
您无需从BaseApi扩展以调用其上的方法。
答案 1 :(得分:0)
如果您需要模拟父类的方法(例如 Directive),您可以通过测试类的存根扩展来实现。
spyObject = {
methodToSpyOn(){}
};
@Directive({selector: '[myDirective]'})
class MyStubDirective extends MyDirective {
parentMethodToMock() {
return spyObject.methodToSpyOn();
}
}
spyOn(spyObject, 'methodToSpyOn').and.returnValue(true);
如果您的类在构造函数中有父方法调用,通常需要这种方法