我已经定义了一个接口和不透明令牌,如下所示
export let AUTH_SERVICE = new OpaqueToken('auth.service'); export interface AuthService { logIn(): void; logout(): void; }
在我的测试类中,我提供了一个AuthService的存根版本,即
@Injectable() class AuthServiceStub implements AuthService { logIn(): void {} logout(): void {} }
并在之前设置我的测试,如下所示
beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ LoginComponent ],providers: [ {provide: AUTH_SERVICE,useValue: AuthServiceStub} ] }); }));
然后我开始写测试,即,
it('should call log in on AuthService',() => { let authService = fixture.debugElement.injector.get(AUTH_SERVICE); spyOn(authService,'logIn'); // expect will go here });
但是我收到以下错误
Error: <spyOn> : logIn() method does not exist
看不出我做错了什么.有任何想法吗?
解决方法
那是因为你在提供者对象中使用了useValue属性.这意味着注入的值将是AuthServiceStub类本身.你想要的是它实际拥有这些方法的实例.
要使测试有效,请将useValue替换为useClass.这将使Angular的依赖注入系统在创建提供程序时实际实例化服务,并调用fixture.debugElement.injector.get(AUTH_SERVICE);将返回一个适当的对象.
或者,您可以手动实例化该类:
it('should call log in on AuthService',() => { let AuthService = fixture.debugElement.injector.get(AUTH_SERVICE); let authService = new AuthService(); spyOn(authService,'logIn'); // expect will go here });
仍然,useClass是一个更好的解决方案,因为它将处理AuthService可能需要的所有未来注入.