2016-11-30 58 views
6

角2先进的测试文档:角2提供程序为什么{useValue:...}克隆对象?

userServiceStub = { 
    isLoggedIn: true, 
    user: { name: 'Test User'} 
}; 

TestBed.configureTestingModule({ 
    declarations: [ WelcomeComponent ], 
// providers: [ UserService ] // NO! Don't provide the real service! 
            // Provide a test-double instead 
    providers: [ {provide: UserService, useValue: userServiceStub } ] 
}); 

fixture = TestBed.createComponent(WelcomeComponent); 
comp = fixture.componentInstance; 

// UserService actually injected into the component 
userService = fixture.debugElement.injector.get(UserService); 
componentUserService = userService; 
// UserService from the root injector 
userService = TestBed.get(UserService); 

似乎从我们明确创建的服务,userService形式injector.get()和userServiceStub是不同的对象。

it('stub object and injected UserService should not be the same',() => { 
    expect(userServiceStub === userService).toBe(false); 

    // Changing the stub object has no effect on the injected service 
    userServiceStub.isLoggedIn = false; 
    expect(userService.isLoggedIn).toBe(true); 
}); 

的文档说,userService这里是userServiceStub副本。这是否意味着Angular 2 DI会将所有{provide: someting, useValue: someValue}视为克隆新对象frome someValue?为什么DI系统不直接使用someValue

Angular.io相关github上issue

+0

您是否在WelcomeComponent中提供了'UserService'? –

+0

@GünterZöchbauer我在root appModule中提供普通的userService。我的问题是,为什么不直接在这里注入userServiceStub,而是将它克隆。 appModule中似乎没有原始的userService。 – MaxLXJ

+0

我没有注入一个克隆。 DI从不克隆。很难分辨您的代码究竟发生了什么。你能否提供一个Plunker来重现? –

回答

3

Angular2 DI为每个提供者维护一个实例。如果多次提供一个键(类型,字符串或OpaqueToken),您将获得多个实例。

在您的示例中,UserService由测试模块提供,DI将始终从该模块返回相同的实例,但是如果具有相同键的提供程序更接近请求依赖关系的位置(例如组件本身,然后从该供应商的情况下将被注入

要覆盖测试的行为有不同的方式,取决于具体的使用情况

一个例子:。

TestBed.overrideComponent(comp, {set /* or add */: 
    {providers: [/* new providers here */]} 
}); 

更新

有一个相关的悬而未决的问题https://github.com/angular/angular/issues/10788 看来,这实际上不能按预期工作。