您可以在将服务注入经过测试的组件之前手动实例化该服务吗?

时间:2019-11-01 23:54:34

标签: angular unit-testing angular-test

我正在尝试在Angular中测试组件ProfileComponentProfileComponent通过注入依赖于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 个答案:

答案 0 :(得分:1)

如果要测试组件,则需要使用假服务与之交互。 不必配置测试模块两次,您应该执行类似的操作

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值。通常,您应该对每种服务(组件,管道等)使用类似的策略,以便您的测试仅测试组件。如果您使用真实的依赖项,则可能要冒使它们的代码影响组件测试的风险。这也使您可以控制依赖项返回的内容,并测试组件是否正确处理了每个不同的响应。