簡體   English   中英

角度:如何在單元測試中模擬擴展類

[英]angular: How to mock extends class in unit test

我有一個可注入服務(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檢查控制台。 我希望你走上正軌!! 登錄但收到為不應該在這里...

無法進一步發展。 有人可以糾正我的錯誤嗎?

您正在嘗試做的事情不起作用。 依賴注入和類繼承沒有直接關系。 這意味着您不能像這樣切換服務的基類。

在我看來,您有兩種方法可以做到這一點。

選項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 擴展來調用它的方法。

如果您需要模擬父類的方法(例如 Directive),您可以通過測試類的存根擴展來實現。

spyObject = {
  methodToSpyOn(){}
};

@Directive({selector: '[myDirective]'})
class MyStubDirective extends MyDirective {
  parentMethodToMock() {
    return spyObject.methodToSpyOn();
  }
}

spyOn(spyObject, 'methodToSpyOn').and.returnValue(true);

如果您的類在構造函數中有父方法調用,則通常需要這種方法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM