angular - 如何在没有测试平台的情况下模拟非类、非导出变量
问题描述
我有大量需要测试的服务。类测试,而不是组件测试,因此我不能使用 Testbed,但必须使用let service = new MyService
. 但是,这些服务中有一小部分使用既不是类变量也不是导出的硬编码对象。
如何访问这些变量并使它们可用于构造函数?
我的.service.ts
import { Injectable, Inject } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs';
import { ServicedItem } from '../../models/serviced-item.model';
const headers = new HttpHeaders() // <--- How to mock this???
.append('appended stuff here');
export class MyService {
constructor(
private readonly httpClient: HttpClient,
@Inject('env') private env,
) {}
public getServicedItem(id: string): Observable<ServicedItem> {
return this.httpClient.get<ServicedItem>(
`${this.env.webApiBaseUrl}servicedItem/${id}`,
{ headers }
);
}
}
我的.service.spec.ts
import { HttpClientModule } from '@angular/common/http';
import { MyService } from './my.service';
jest.mock('@angular/common/http');
describe('MyService', () => {
let service: MyService;
const webApiBaseUrl: string = 'mocky-yeah'
const env = { 'webApiBaseUrl': webApiBaseUrl } as any;
const id: string = 'THE_id';
const testPayload: string = 'Insert correct string here';
describe('CLASS: mocked backend tests', () => {
const httpClient: any = { get: jest.fn() };
beforeEach(() => {
service = new MyService(httpClient, env);
});
test('should be created', () => {
expect(service).toBeTruthy();
});
describe('METHOD: getServicedItem', () => {
test('should return servicedItem', (done) => {
httpClient.get.mockImplementationOnce(() => of(testPayload));
service.getServicedItem().subscribe((res) => {
expect(httpClient.get).toBeCalledWith(`${webApiBaseUrl}servicedItem/${id}`);
expect(res).toBe(testPayload);
done();
}, done.fail)
});
});
});
照原样,我得到一个 TypeError: Cannot read property 'append' of undefined on the headers。我已经寻找方法来做到这一点......让我们说很久了。但是我发现的所有教程要么假设 Testbed,要么去上课或至少导出变量。但是必须有办法做到这一点,对吧?
并抛出错误:
● Test suite failed to run
TypeError: Cannot read property 'append' of undefined
4 | import { ServicedItem } from '../../models/serviced-item.model';
5 | >
6 | const headers = new HttpHeaders()
| ^
7 | .append('Content-Type', 'application/json')
编辑:
在一些输入后添加精确的错误块。
解决方案
您遇到的问题是由
jest.mock('@angular/common/http');
在测试中。尝试将其删除,或正确模拟其导出。
import { HttpHeaders } from '@angular/common/http';
import { of } from 'rxjs';
import { MyService } from './my.service';
describe('MyService', () => {
let service: MyService;
const webApiBaseUrl = 'mocky-yeah';
const env = {webApiBaseUrl} as any;
const id = 'THE_id';
const testPayload = 'Insert correct string here';
describe('CLASS: mocked backend tests', () => {
const httpClient: any = {get: jest.fn()};
beforeEach(() => {
service = new MyService(httpClient, env);
});
test('should be created', () => {
expect(service).toBeTruthy();
});
describe('METHOD: getServicedItem', () => {
test('should return servicedItem', async () => {
httpClient.get.mockImplementationOnce(() => of(testPayload));
const res = await service.getServicedItem(id).toPromise();
expect(httpClient.get).toHaveBeenCalledWith(
`${webApiBaseUrl}servicedItem/${id}`,
{
headers: jasmine.any(HttpHeaders),
},
);
expect(res).toBe(testPayload);
});
});
});
});
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Inject } from '@angular/core';
import { Observable } from 'rxjs';
const headers = new HttpHeaders() // <--- How to mock this???
.append('Foo', 'Bar');
export class MyService {
public constructor(
private readonly httpClient: HttpClient,
@Inject('env') private env,
) {}
public getServicedItem(id: string): Observable<any> {
return this.httpClient.get<any>(
`${this.env.webApiBaseUrl}servicedItem/${id}`,
{ headers },
);
}
}
推荐阅读
- android - Android Gradle 插件 `registerTransform` 不再对 4.1.x 及更高版本的插件开发者公开
- oracle11g - 同义词不起作用 ORA-00980: 同义词翻译不再有效?
- c# - .NET Core 控制台应用程序如何部署到 Kubernetes?
- amazon-s3 - 如何使用 C# AWS SDK 从 S3 一次下载多个文件
- python - 为什么我在 python3 中得到一个`NameError: name '_ORIENTATION' is not defined`
- python - 在这种情况下如何使用乌龟
- ansible - 尝试在我的 Ansible playbook 中创建用户时出错?
- java - MouseMotionListener 似乎闹鬼
- devops - 我们如何有条件地运行 CircleCI 工作流程?
- google-apps-script - 带有保护的复制表并将新副本的名称更改为日期