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

Can you instantiate a service manually before it is injected into a tested component?

我正在尝试测试 Angular 中的组件 ProfileComponentProfileComponent 通过注入依赖 AuthenticationService:

profile.component.ts

constructor(public authenticationService: AuthenticationService) { }

我的 ProfileComponent 只是一个页面,除非用户登录,否则无法导航到该页面,因为如果 authenticationService.isLoggedIn() return,我的路由器会将所有导航从该页面重新路由s false.

因此,我在 ProfileComponent 中的代码期望 authenticationService.isLoggedIn() 到 return 为真,并且永远不会检查它。相反,它会根据当前登录的用户执行代码,如果没有用户实际登录,代码就会中断。

我正在尝试测试 ProfileComponent,但是 AuthenticationService 对象在我调用 authenticationService.logIn(username, password) 停止 ProfileComponent 中的代码之前被注入 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`.

有没有一种方法可以让我在将服务注入正在测试的组件之前对其执行一些操作?

如果您要测试您的组件,您将需要使用虚假服务来与之交互。 不要两次配置测试模块,你应该做类似

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

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

然后在您的提供商中您将拥有

{
  provide: AuthenticationService,
  useValue: fakeAuthenticationService
}

现在,当您的测试运行时,您的组件将收到来自 isLoggedIntrue 值。通常,您应该对每个服务(组件、管道等)使用类似的策略,以便您的测试仅测试组件。如果您使用真正的依赖项,您可能会冒着让它们的代码影响组件测试的风险。这还允许您控制依赖项 return 并测试您的组件是否正确处理每个不同的响应。