javascript - Angular 7 测试依赖于私有方法的公共方法
问题描述
我正在使用 Angular 7.1 和 Jasmine 来测试我的组件。我正在尝试编写一些测试,但这对我来说似乎太多了。
我正在尝试测试的简化类:
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'a',
templateUrl: './a.html',
styleUrls: ['./a.scss']
}
export class A implements OnInit {
constructor(private http: HttpClient) {}
private privateState: State;
public publicState: State2;
ngOnInit() {
this.http.get(this.GetUrl()).subscribe((x) => {
this.privateState = x['whatever'];
});
}
private hiddenComplexFunction() {
this.publicState = this.privateState.something;
}
public testedFunction() {
//someComplex Code
this.hiddenComplexFunction();
}
}
我试过的:
- 我试图设置私有变量,
A.['privateState']
但没有工作 - 我尝试使用 SpyOn http get,但遇到了同样的问题,必须设置私有属性
- 我尝试使用 HttpClientTestingModule 但我遇到了与前一点相同的问题
最后,我尝试使 privateState 受保护并以下列方式对其进行测试:
import { HttpClientTestingModule } from '@angular/common/http/testing'; import { async, ComponentFixture, TestBed } from '@angular/core/testing'; class AMock extends A { ngOnInit() { //privateState is now protected this.privateState = mockedState; } } describe('A', () => { let component: AMock; let fixture: ComponentFixture<AMock>; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], declarations: [AMock] }) .compileComponents().catch(); })); beforeEach(() => { fixture = TestBed.createComponent(AMock); component = fixture.componentInstance; }); it('testedFunction should set up public state correctly', () => { component.testedFunction(); expect(component.publicState).toEqual(mockedState.something); });
ng test
最后一点不起作用,因为运行命令后无法读取未定义的属性“testedFunction”而返回错误。
我不知道哪种方法是测试这个的正确方法。我知道我可以hiddenComplexFunction
公开,我所有的问题都消失了,而且我不喜欢这样一个事实,即由于测试我必须更改访问修饰符(从私有到受保护的,就像在模拟示例中一样,这对我来说似乎都是错误的)。
解决方案
你的问题有很多内容,所以我将从我容易看到的事情开始。
我们可以从您的核心组件代码开始。在您的testedFunction() 中,调用this.hiddenComplexFunction()。你想要函数的实例版本,所以需要添加 ""this."" 到它。这是非常合适的,无论如何您都不想直接测试私有函数/私有属性。
接下来,我猜你想要这段代码
this.state = x['whatever'];
设置您的 privateState,而不是状态
this.privateState = x['whatever'];
接下来,您不需要使用 AMock 类模拟 A,测试装配将为您完成。尝试以下类似的方法作为开始。我在这里没有的是州代码。我真正做的就是摆脱你的 AMock 并用实际的组件替换它,并构建一个测试状态(我可能会添加一个糟糕的状态构建。哈!)。我处理下面的 HTTP 数据,这将与我通过查看您的代码猜测的状态有关。
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { A } from './zing.component'; // this should point to your component
// get rid of this, not needed
// class AMock extends A {
// ngOnInit() {
// //privateState is now protected
// let privateState = mockedState;
// }
// }
describe('A', () => {
let component: A; // changed from AMock to A
let fixture: ComponentFixture<A>; // changed from AMock to A
let mockedState = {something: 'yelp'}; // build your expected state here
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
declarations: [A] // changed from AMock to A
})
.compileComponents().catch();
}));
beforeEach(() => {
fixture = TestBed.createComponent(A); // changed from AMock to A
component = fixture.componentInstance;
});
it('testedFunction should set up public state correctly', () => {
component.testedFunction();
expect(component.publicState).toEqual(mockedState.something);
});
});
最后,对于您的 HTTP 模拟,您可以使用 HttpTestingController 将一些数据刷新到您的组件。
在描述块中 -
let backend: HttpTestingController;
在每个之前 -
backend = TestBed.get(HttpTestingController);
在您的 IT 声明中 -
backend.expectOne(expectedURL).flush(mockedState);
backend.verify();
让我们知道这对您有多大帮助,是否有帮助或您是否遇到其他错误。
推荐阅读
- c# - HttpClient 调用保持等待模式,但在控制台应用程序中工作正常
- macos - 从 AppleScript 获取 Apple 事件
- java - 如何从Java中的方法返回列表
- java - 创建不带 SecurityException 的 fatJar
- wordpress - Wordpress 循环重复帖子
- java - 从 SQLite 数据库中检索图像并在 ListView 中显示
- django - Django:没有在 iframe 中设置 CSRF Cookie——没有 csrf 豁免的解决方法
- excel - 两个excel文件的VBA比较
- javascript - 边界框 konva js 中的变压器控件
- azure - Azure 应用服务丢失传入请求