我已经阅读了整个angular.io测试文档,搜索了关键字并使用了S.O.的高级搜索。但没有发现任何适用于我的情况。我是单元测试的新手,所以也许我还没有这个术语。如果这是重复的,请指出我正确的方向。
预示:我的问题是
A。)angular / jasmine是否能够从模板方法调用中测试动态参数。
或者......
B。)在每个fixture.detectChanges()中你如何模拟传递参数到方法?
这是情况和失败的代码......
<generic-element
*ngFor=”let recordObj of recordsArray”
[ngClass]=”doSetClasses(recordObj)”
></generic-element>
总之,我有一个组件模板,其中一个元素动态地获取它通过方法分配的类。此方法接受一个对象(通过ngFor指令从列表中提取)并检查它以确定它应返回给模板的类名。我更喜欢通过方法分配真正详细的分配,因为我试图将我的逻辑保留在typescript文件和HTML中的结构......至少尽可能多。
我非常简单的单元测试失败了,因为“无法读取未定义的属性'id'(在这种情况下未定义的是从模板传递到doSetClasses()方法的recordObj。我已经将它隔离了,因为如果我只是覆盖并去除测试环境中doSetClasses方法的内容,一切都通过,例如:
beforeEach {
...
component.doSetClasses = function() { return; } as any;
}
现在如果我按原样保留doSetClasses方法,我注意到如果我不调用fixture.detectChanges()它也会通过。所以我的问题似乎是:测试方法,从模板中调用,在角度变化检测/摘要周期中也包含模板中包含的参数。
我的问题是
A。)angular / jasmine是否能够从模板方法调用中测试动态参数。
或者......
B。)在测试环境中的每个fixture.detectChanges()期间,你如何模拟将参数传递给方法?
同样,如果这是重复的,请指出我正确的方向。
提前感谢您的任何帮助,建议和指导。非常感谢。
答案 0 :(得分:0)
在几天没有答案,评论或问题之后,似乎没有提交任何指导。所以对于今后可能会发现类似问题的人来说,这就是我所得到的:
我目前无权访问我的代码,但这是简写:
beforeEach() {
//Create a copy to use in controlled scenarios
const doSetClassesCopy = doSetClasses;
//Then strip out contents so it can be called but does not error during testing
doSetClasses = function() { return; } as any;
}
...
(The Test)
//Now mock it's performance with params from template's *ngFor directive
const simulatedParamsFromTemplate = { value: 'whatever' } as recordObj;
const outcome = doSetClassesCopy(simulatedParamsFromTemplate);
expect(outcome).toBe('Whatever I expect.');
如果有人有更好的解决方案或建议,我有兴趣听取它。感谢。
答案 1 :(得分:0)
我今天也遇到了类似的问题。调用fixture.detectChanges()
似乎会触发调用ngClass
中提到的函数。
我想调用validateField
,它将把Bootstrap
的类分配给控件
HTML
<form class="form-inline" [formGroup]="loginForm" (ngSubmit)="signInUser()" novalidate>
<input type="text" id="username" class="form-control" placeholder="username" formControlName="userName" [ngClass]="validateField('userName')" required>
<input type="password" id="password" class="form-control" placeholder="password" formControlName="password" [ngClass]="validateField('password')" required>
...
validateField
中的.ts
函数是
/*
This function will eventually return object of type depending on whether the field is valid or not, set Bootstrap's css
{
'is-invalid': true or false, // if fieldvalid returns false i.e. field is not valid then we want has-error css. So set it to true (opp. of fieldValid)
'is-valid': true or false //if fieldvalid returns true i.e. field is valid then we want has-success css. So set it to true (value of fieldValid)
}
*/
validateField(field:string){
// console.log("validating field: " +field)
return this.helper.validateField(this.loginForm,field);
}
我的spec
是
fit('it should validate that the data in username and password field has correct format',()=>{
let navComponent = component;
let helperService = TestBed.get(HelperService);
spyOn(helperService,'validateField');
let formControls = navComponent.loginForm.controls;
let email = 'test@test.com';
let password = 'testpassword';
formControls['userName'].setValue(email);
fixture.detectChanges(); //<-- THIS SEEM TO TRIGGER THE CALLING OF VALIDATION FUNCTION
expect(helperService.validateField).toHaveBeenCalledWith(navComponent.loginForm,'userName');
formControls['password'].setValue(password);
fixture.detectChanges();//<-- THIS SEEM TO TRIGGER THE CALLING OF VALIDATION FUNCTION
expect(helperService.validateField).toHaveBeenCalledWith(navComponent.loginForm,'password');
});