angular: как издеваться над классом в модульном тесте - PullRequest
0 голосов
/ 01 июня 2018

У меня есть инъекционный сервис (EntityApi), который расширяет класс (BaseApi).В моей спецификации мне нравится издеваться над BaseApi с BaseApiStub.Но это напрасно.Всегда звоню в 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 Ответ

0 голосов
/ 01 июня 2018

То, что вы пытаетесь сделать, не работает.Инъекция зависимостей и наследование классов напрямую не связаны.Это означает, что вы не можете переключить базовый класс своего сервиса следующим образом.

На мой взгляд, у вас есть два способа сделать это.

Вариант 1:

Вместо насмешки над BaseApi и предоставления имитации в вашем тесте, вам нужно смоделировать EntityApi и предоставить этот макет в своем тесте.

Вариант 2:

Вместо того чтобы позволить EntityApi расширяться от BaseApi, вы можете оставить 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 для вызова методов на нем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...