![](/img/trans.png)
[英]How to allow partial TypeScript types when mocking functions - Jest, TypeScript
[英]Mocking Express Request with Jest and Typescript using correct types
我在 Jest 中获得正确的 Express Request 类型时遇到了一些麻烦。 我有一个使用此代码传递的简单用户注册:
import { userRegister } from '../../controllers/user';
import { Request, Response, NextFunction } from 'express';
describe('User Registration', () => {
test('User has an invalid first name', async () => {
const mockRequest: any = {
body: {
firstName: 'J',
lastName: 'Doe',
email: 'jdoe@abc123.com',
password: 'Abcd1234',
passwordConfirm: 'Abcd1234',
company: 'ABC Inc.',
},
};
const mockResponse: any = {
json: jest.fn(),
status: jest.fn(),
};
const mockNext: NextFunction = jest.fn();
await userRegister(mockRequest, mockResponse, mockNext);
expect(mockNext).toHaveBeenCalledTimes(1);
expect(mockNext).toHaveBeenCalledWith(
new Error('First name must be between 2 and 50 characters')
);
});
});
但是,如果我改变:
const mockRequest: any = {
body: {
firstName: 'J',
lastName: 'Doe',
email: 'jdoe@abc123.com',
password: 'Abcd1234',
passwordConfirm: 'Abcd1234',
company: 'ABC Inc.',
},
};
至:
const mockRequest: Partial<Request> = {
body: {
firstName: 'J',
lastName: 'Doe',
email: 'jdoe@abc123.com',
password: 'Abcd1234',
passwordConfirm: 'Abcd1234',
company: 'ABC Inc.',
},
};
从 TypeScript 文档 ( https://www.typescriptlang.org/docs/handbook/utility-types.html#partialt ) 来看,这应该使 Request 对象上的所有字段都是可选的。
但是,我收到此错误:
Argument of type 'Partial<Request>' is not assignable to parameter of type 'Request'.
Property '[Symbol.asyncIterator]' is missing in type 'Partial<Request>' but required in type 'Request'.ts(2345)
stream.d.ts(101, 13): '[Symbol.asyncIterator]' is declared here.
我希望有更多 TypeScript 经验的人可以发表评论并让我知道我做错了什么。
您的模拟数据类型不必完全适合实际数据。 好吧,它不是根据定义。 这只是一个模拟,对吧?
您需要的是类型断言。 这是一种告诉 TypeScript “好的兄弟,我知道我在这里做什么”的方式。 .
这不是生产代码,而是测试。 您甚至可能在手表模式下运行它。 我们可以在这里毫无问题地拒绝某些类型安全。 TypeScript 不知道它是一个模拟,但我们知道。
const mockRequest = {
body: {
firstName: 'J',
lastName: 'Doe',
email: 'jdoe@abc123.com',
password: 'Abcd1234',
passwordConfirm: 'Abcd1234',
company: 'ABC Inc.',
},
} as Request;
如果在测试过程中发生崩溃,因为mockRequest
与 Request 不够相似,我们会知道并修复 mock,添加一些新属性等。
如果as Request
不起作用,你可以告诉 TypeScript “我真的知道我在这里做什么” ,首先断言any
或unknown
然后再断言你需要的类型。 它看起来像
const x: number = "not a number :wink:" as any as number;
当我们想测试我们的代码在输入错误的情况下不能很好地工作时,它很有用。
对于您的特定情况 - 模拟快递请求 - 如果您当然可以节省 node_modules 的大小,则可以使用jest-express来帮助您。
为了将来搜索这个主题,我建议查看这个库: https ://www.npmjs.com/package/node-mocks-http
该库具有为 Express 框架的请求和响应创建模拟对象的方法,这对我有很大帮助,并且是我找到的简单方法。
简单的单元测试示例:
import { Request, Response } from 'express';
import {
createRequest, createResponse, MockRequest, MockResponse,
} from 'node-mocks-http';
import { AppController } from './app-controller';
import { APP_NAME, APP_VERSION } from '../../constants';
describe('AppController - UnitTestCase', () => {
let controller: AppController;
let request: MockRequest<Request>;
let response: MockResponse<Response>;
beforeEach(() => {
controller = new AppController();
/** Response Mock */
response = createResponse();
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
describe('GET /', () => {
it('should return 200 and API Name + API Version', (done) => {
/** Request Mock */
request = createRequest({
method: 'GET',
url: '/',
});
AppController.index(request, response);
const body = { app: `${APP_NAME}:${APP_VERSION}` };
const result = response._getJSONData();
expect(result).toMatchObject(body);
expect(result.app).toEqual(body.app);
expect(response.getHeaders()).toHaveProperty('content-type');
console.log('headers', response.getHeaders());
console.log('response body', result);
done();
});
});
});
似乎userRegister
是@kschaer 所说的问题。 如果您希望该函数接受Partial<Request>
,您可以将userRegister
更改为:
const userRegister = async (req: Partial<Request>, res: Response, next: NextFunction) => { /* snippet */ }
但由于这只是用于测试,您也可以将mockRequest
转换为Request
类型,如下所示:
const mockRequest = <Request>{
body: {
/* snippet */
}
};
希望这会有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.