Можете ли вы создать службу вручную, прежде чем она будет внедрена в тестируемый компонент? - PullRequest
0 голосов
/ 02 ноября 2019

Я пытаюсь проверить компонент, ProfileComponent в Angular. ProfileComponent зависит от AuthenticationService через инъекцию:

profile.component.ts

constructor(public authenticationService: AuthenticationService) { }

Моя ProfileComponent - это просто страница, на которую нельзя перейти, если пользователь не вошел в системупотому что мой маршрутизатор перенаправляет все переходы с этой страницы, если authenticationService.isLoggedIn() возвращает false.

Мой код в ProfileComponent для этого ожидает, что authenticationService.isLoggedIn() вернет true, и никогда не проверяет его. Вместо этого он выполняет код, основанный на текущем вошедшем в систему пользователе, который прервался бы, если бы пользователь фактически не вошел в систему.

Я пытаюсь проверить ProfileComponent, но объект AuthenticationService введен в ProfileComponent прежде чем я смогу позвонить authenticationService.logIn(username, password), чтобы остановить взлом кода в ProfileComponent.

Вот идея того, что я хотел бы сделать:

profile.component.spec.ts

describe('ProfileComponent', () => {
  let component: ProfileComponent;
  let fixture: ComponentFixture<ProfileComponent>;
  let authenticationService: AuthenticationService;

  beforeEach((done) => {

    // Configure the AuthenticationService's injections
    TestBed.configureTestingModule({
      imports: [
        HttpClientModule
      ]
    });

    // Get the AuthenticationService object
    authenticationService = TestBed.get(AuthenticationService);
    expect(authenticationService).toBeTruthy();

    // Make sure authentication service is logged in
    authenticationService.login(TestVariables.username, TestVariables.password).then(() => {
      // Configure the ProfileComponent's injections, passing the already logged in AuthenticationService
      TestBed.configureTestingModule({
        declarations: [ ProfileComponent ],
        schemas: [CUSTOM_ELEMENTS_SCHEMA],
        imports: [HttpClientModule],
        providers: [
          {
            provide: AuthenticationService,
            useValue: authenticationService
          }
        ]
      }).compileComponents().then(() => {
        fixture = TestBed.createComponent(ProfileComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
        done();
      });
    });
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

Когда я пытаюсь это сделать, я получаю следующую ошибку:

'Cannot configure the test module when the test module has already been instantiated. Make sure you are not using `inject` before `TestBed.configureTestingModule`.

Есть ли способ, которым я могу выполнить некоторые операции с моим сервисом перед его внедрением в компонент, которыйпроверяется?

1 Ответ

1 голос
/ 02 ноября 2019

Если вы собираетесь тестировать свой компонент, вы захотите использовать поддельный сервис для взаимодействия с ним. Вместо того, чтобы настраивать тестовый модуль дважды, вы должны сделать что-то похожее на

const fakeAuthenticationService = jasmine.createSpyObj<AuthenticationService>('auth', ['isLoggedIn']);

// set the response to isLoggedIn
fakeAuthenticationService.isLoggedIn = jasmine.createSpy('isLoggedIn').and.returnValue(true);

Тогда у ваших провайдеров у вас будет

{
  provide: AuthenticationService,
  useValue: fakeAuthenticationService
}

Теперь, когда ваш тест будет запущен, ваш компонент получит true значение от isLoggedIn. В целом, вы должны использовать аналогичную стратегию для каждого сервиса (компонента, канала и т. Д.), Чтобы ваш тест проверял ТОЛЬКО компонент. Если вы используете реальные зависимости, вы рискуете, что их код повлияет на тест для вашего компонента. Это также позволяет вам контролировать то, что возвращают ваши зависимости, и проверять, правильно ли ваш компонент обрабатывает каждый отдельный ответ.

...