gpt4 book ai didi

angular - 如何在 Angular Testing 中向特定测试用例注入(inject)另一项服务

转载 作者:行者123 更新时间:2023-11-28 20:38:15 31 4
gpt4 key购买 nike

如上述标题问题 - 是否可以将服务的另一个实例注入(inject)特定的测试功能?我的意思是,在测试服中,我在 beforeEach 方法中注入(inject)了一些服务。

创建 stub :

let userServiceStub = {
hasReadPermissions() { return true; },
isUserInformationAvailable() { return true; },
isUserRequestForbidden() { return true; }
};

在beforeEach方法中配置测试模块:

TestBed.configureTestingModule({
declarations: [
SomeComponent
],
providers: [{ provide: UserService, useValue: userServiceStub },
{ provide: AnotherService, useValue: anotherServiceStub }],
schemas: [ NO_ERRORS_SCHEMA ]
}).compileComponents();

然后我必须测试用例:

首先我想在 TestBed 中使用注入(inject)的服务 stub

it('should render topbar when user has read permissions', () => {
let topbar = debugElement.query(By.css('topbar'));
expect(topbar).toBeTruthy();
});

第二,我想使用同一服务的另一个 stub :

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');
}));

或者也许我试图以不恰当的方式进行操作?请指出正确的方法。

[[编辑]]

部分组件逻辑:

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();
}

模板:

<ng-container *ngIf="hasUserReadPermissions()">
<topbar></topbar>
<main-menu></main-menu>
<router-outlet></router-outlet>
</ng-container>
<div class="row" *ngIf="dataUnavailable">
<div class="col-sm-12">
<h2 class="text-center rcm-bold-message">Server data is not available.</h2>
</div>
</div>
<div class="row" *ngIf="noPermissions">
<div class="col-sm-12">
<h2 class="text-center rcm-bold-message">You do not have sufficient permissions.</h2>
</div>
</div>

最佳答案

好的,正如我在对您的问题的评论中所说,您基本上可以在组件测试中忽略服务的实际响应(因为服务方法的结果无论如何都应该单独测试)。

如果你想改变返回值,这样你就不必保留不同的 stub 或这些 stub /服务的实例,你可以使用 jasmine.Spy 来监视这个方法并使用提供的方法 returnValue 来定义将在您的测试中返回的值:

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');

只是关于您的组件的快速提示:您正在使用 *ngIf 中的方法。没关系,大多数时候,但请记住,这个函数将在 Angular 生命周期 Hook 的每个摘要循环中调用(意味着在 ngOnInitngAfterViewInitngDoCheck 等)。这将导致您的函数在一秒钟内被多次调用。不要使用有些“慢”的方法(我知道,慢是相对的)。在您的组件内调用该函数一次,保留对返回值的引用,就像您对 dataUnavailable 所做的那样。

希望对您有所帮助。


完成更新:

有时,您不想在测试中模拟一个方法,尽管它被调用了,而是阻止调用它的实际实现(可能是因为它做了您不关心的事情关于你的测试,或者它有依赖关系或数千个嵌套的可观察对象或简单的超时,这些都是测试的困惑)。在这种情况下,您实际上可以重写该函数:

  comp.userService.hasUserReadPermissions = function() { return false; };
// do some stuff so the function is called
expect(...).toBe(...);

看似丑陋,但有时确实能保住性命。

关于angular - 如何在 Angular Testing 中向特定测试用例注入(inject)另一项服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45855982/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com