Angular 7 个测试 public 方法依赖于私有方法
Angular 7 testing public methods dependent on private ones
我正在使用 angular 7.1 和 Jasmine 来测试我的组件。我正在尝试编写一些测试,但这个对我来说似乎太多了。
简化的class我正在尝试测试:
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
public 并且我所有的问题都消失了而且我不喜欢这样一个事实,因为测试我将不得不更改访问修饰符(从私有到受保护,就像在嘲笑的例子对我来说似乎都是错误的)。
你的问题涉及很多,所以我将从我容易看到的事情开始。
我们可以从您的核心组件代码开始。在您的 testedFunction() 中,调用 this.hiddenComplexFunction()。您想要函数的实例版本,因此需要向其添加“"this."”。它非常合适,无论如何您都不想直接测试私有 functions/private 属性。
接下来,我猜你想要这段代码
this.state = x['whatever'];
设置你的私有状态,而不是状态
this.privateState = x['whatever'];
接下来,您无需使用 AMock class 模拟 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();
让我们知道这对您有多大帮助,或者如果您遇到其他错误。
我正在使用 angular 7.1 和 Jasmine 来测试我的组件。我正在尝试编写一些测试,但这个对我来说似乎太多了。
简化的class我正在尝试测试:
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
public 并且我所有的问题都消失了而且我不喜欢这样一个事实,因为测试我将不得不更改访问修饰符(从私有到受保护,就像在嘲笑的例子对我来说似乎都是错误的)。
你的问题涉及很多,所以我将从我容易看到的事情开始。
我们可以从您的核心组件代码开始。在您的 testedFunction() 中,调用 this.hiddenComplexFunction()。您想要函数的实例版本,因此需要向其添加“"this."”。它非常合适,无论如何您都不想直接测试私有 functions/private 属性。
接下来,我猜你想要这段代码
this.state = x['whatever'];
设置你的私有状态,而不是状态
this.privateState = x['whatever'];
接下来,您无需使用 AMock class 模拟 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();
让我们知道这对您有多大帮助,或者如果您遇到其他错误。