How to inject another service to specific test case in angular testing
与上述标题问题一样-是否可以将服务的另一个实例注入特定的测试功能?我的意思是这样的情况:在测试服中,我在beforeEach方法中注入了一些服务。
创建Stubbing:
1 2 3 4 5 | let userServiceStub = { hasReadPermissions() { return true; }, isUserInformationAvailable() { return true; }, isUserRequestForbidden() { return true; } }; |
在配置测试模块的beforeEach方法中:
1 2 3 4 5 6 7 8 | TestBed.configureTestingModule({ declarations: [ SomeComponent ], providers: [{ provide: UserService, useValue: userServiceStub }, { provide: AnotherService, useValue: anotherServiceStub }], schemas: [ NO_ERRORS_SCHEMA ] }).compileComponents(); |
然后我要测试案例:
首先要在TestBed
中使用注入的服务Stubbing
1 2 3 4 | it('should render topbar when user has read permissions', () => { let topbar = debugElement.query(By.css('topbar')); expect(topbar).toBeTruthy(); }); |
第二个我想使用同一服务的另一个Stubbing的地方:
1 2 3 4 5 6 7 8 9 10 11 | let anotherUserServiceStub = { hasReadPermissions() { return false; }, isUserInformationAvailable() { return false; }, isUserRequestForbidden() { return true; } }; it('should render appropriate message when user has not read permissions', inject([UserService], (userService: UserService) => { <--- how to inject another user service stub here? let message = debugElement.query(By.css('h2')); expect(message).toBe('you have no permissions'); })); |
或者也许我正在尝试以所有不合适的方式进行操作?请指出正确的方法。
[[编辑]]
组件逻辑的一部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | dataUnavailable: boolean = false; noPermissions: boolean = false; constructor(private toastr: ToastsManager, vRef: ViewContainerRef, private userService: UserService, private router: Router) { this.toastr.setRootViewContainerRef(vRef); } ngOnInit(): void { if (!this.isUserInformationAvailable()) { if (this.isUserRequestForbidden()) { this.noPermissions = true; } else { this.dataUnavailable = true; this.toastr.error("An error occured while getting data from server."); } } } hasUserReadPermissions(): boolean { return this.userService.hasReadPermissions(); } |
模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <ng-container *ngIf="hasUserReadPermissions()"> <topbar></topbar> <main-menu></main-menu> <router-outlet></router-outlet> </ng-container> <h2 class="text-center rcm-bold-message">Server data is not available. <h2 class="text-center rcm-bold-message">You do not have sufficient permissions. |
好吧,正如我在对您的问题的评论中所说的那样,您基本上可以在对组件进行测试时忽略服务的实际响应(因为服务方法的结果,无论如何都应单独测试)。
如果要更改返回值,而不必保留其他Stubbing或这些Stubbing/服务的实例,则可以使用
1 2 3 4 | let spy: jasmine.Spy = spyOn(comp.userService, 'hasUserReadPermissions').and.returnValue(false); let message = debugElement.query(By.css('h2')); expect(message).toBe('you have no permissions'); |
关于组件的快速提示:您正在
希望有帮助。
完成更新:
有时,尽管调用了该方法,但您仍不想在测试中模拟该方法,但可以通过其实际实现阻止对该方法的调用(也许是因为它确实执行了您在测试中不需要关心的事情,或它具有依赖项或成千上万个嵌套的可观察变量或简单的超时,这很麻烦进行测试)。在这种情况下,您实际上可以覆盖该函数:
1 2 3 | comp.userService.hasUserReadPermissions = function() { return false; }; // do some stuff so the function is called expect(...).toBe(...); |
看上去很丑,但有时却可以过安全的生活。
此解决方案对我有用,希望它对您也有用
1 2 3 4 5 6 | it('should render appropriate message when user has not read permissions', inject([UserService, AnotherService], (userServiceStub: UserService, anotherServiceStub: AnotherService ) => { let message = debugElement.query(By.css('h2')); expect(message).toBe('you have no permissions'); })); |
我刚刚添加了另一个服务,用逗号分隔。
首先,您提供的信息很少,是有关如何在组件或服务中设置用户的?
注入后,您可以使用spyOn并返回您的用户。
spyOn(userService,\\'getUser \\')。and.returnValue(yourUser);