我有一个恼人的错误,可能由于我的错误,我无法解决。 我有一个简单的组件,它实际上只不过是我的Web应用程序中的顶级元素。
您可以看到此组件只有一个依赖项UserService
,并且它非常简单地使用它:
import { Component, OnInit } from '@angular/core';
import { MdButton } from '@angular2-material/button';
import { MdIcon , MdIconRegistry} from '@angular2-material/icon';
import { UserService } from '../services/index';
import { RouteConfig, ROUTER_DIRECTIVES, Router, ROUTER_PROVIDERS
} from '@angular/router-deprecated';
@Component({
moduleId: module.id,
selector: 'top-bar',
templateUrl: 'top-bar.component.html',
styleUrls: ['top-bar.component.css'],
providers: [MdIconRegistry, UserService, ROUTER_PROVIDERS],
directives: [MdButton, MdIcon, ROUTER_DIRECTIVES]
})
export class TopBarComponent implements OnInit {
constructor(private userService: UserService) {
this.userService = userService;
}
ngOnInit() {
}
/**
* Call UserService and logout() method
*/
logout() {
this.userService.logout();
}
}
由于此服务还有一些依赖项(路由器等),我必须使用beforeEachProviders
方法提供它们,如您所见:
import {
beforeEach,
beforeEachProviders,
describe,
expect,
it,
inject,
} from '@angular/core/testing';
import { TopBarComponent } from './top-bar.component';
import {
Router, RootRouter, RouteRegistry, ROUTER_PRIMARY_COMPONENT
} from '@angular/router-deprecated';
import { provide } from '@angular/core';
import { SpyLocation } from '@angular/common/testing';
import { UserService } from '../services/index';
describe('Component: TopBar', () => {
beforeEachProviders(() => [
RouteRegistry,
provide(Location, { useClass: SpyLocation }),
provide(ROUTER_PRIMARY_COMPONENT, { useValue: TopBarComponent }),
provide(Router, { useClass: RootRouter }),
UserService,
TopBarComponent
]);
it('should inject the component', inject([TopBarComponent],
(component: TopBarComponent) => {
expect(component).toBeTruthy();
}));
});
当我运行测试时,虽然收到此错误消息:
Chrome 51.0.2704(Mac OS X 10.11.5)组件:TopBar应注入组件FAILED 错误:没有位置提供商! (TopBarComponent - > UserService - > Router - > Location) 错误:DI例外[......]
首先,因为您可以看到提供位置提供程序。 secondary ,为什么我的测试需要提供(或注入)使用的依赖项到测试的组件服务?
例如,如果从上面的测试中我删除了路由器,即使我的组件没有使用路由器I也会因为使用的服务而出错。那我不应该在组件中收到相同的错误而不仅仅是在测试中吗?
更新 - 更改代码&错误信息
我已经设法通过将我的规范更改为此来阻止此错误:
import {
beforeEach,
describe,
expect,
it,
} from '@angular/core/testing';
import { TopBarComponent } from './top-bar.component';
import { UserService } from '../services/index';
import {
Router
} from '@angular/router-deprecated';
import { Http } from '@angular/http';
import { AuthHttp } from 'angular2-jwt';
describe('Component: TopBar', () => {
let router: any = Router;
let authHttp: any = AuthHttp;
let http: any = Http;
let component: TopBarComponent;
let service: UserService = new UserService(router, authHttp, http);
beforeEach(() => {
component = new TopBarComponent(service);
});
it('logout function should work ', () => {
let logout = component.logout;
logout();
expect(localStorage.getItem('token')).toBe(null);
});
});
但是知道我从我的组件中得到了这个错误:
TypeError:无法读取属性' userService'未定义的
上述错误出现在此功能上:
logout() {
this.userService.logout();
}
我的组件但这只是在测试中。在应用程序中它正常工作。在我的测试中,函数由于某些原因无法到达构造函数的参数。
这里的堆栈......
答案 0 :(得分:1)
通过您的代码,我了解您正在尝试测试topbar组件。
顶部栏组件依赖于UserService。
因此,为回答您的问题,由于所有提供程序均在模块文件中配置,因此Angular在运行应用程序时会进行依赖项注入。但是,当您尝试测试规格文件中的代码时,您必须使用所有提供程序配置测试平台,beforeEach方法中将要使用的组件和angular承担了将依赖关系解析为用户的全部责任,因为测试平台充当了环境运行代码。
在您的代码中,您可以执行以下操作
让服务:UserService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [UserService, any other service on which user service is dependent] });
});
在这里您可以看到TestBed.configureTestingModule方法创建了一个虚拟模块来帮助您运行测试用例。
我的建议是创建一个模拟UserService,它没有其他依赖项,例如原始的依赖项,并在提供者中分配
类似这样的东西
export MockUserService {
Put all essential methods stub here.
}
let service: UserService;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [provide: UserService, useClass: MockUserService] });
});
然后只测试topBar组件的用例。
答案 1 :(得分:0)
尝试使用TestBed.get(UserService)在beforeEach中创建服务对象。此代码将自动解析依赖关系并创建该对象以供使用。
删除'= new UserService(router,authHttp,http);'来自'let service:UserService = new UserService(router,authHttp,http);'