有没有办法在函数中模拟 Promise.resolve
is there a way to mock the the Promise.resolve in a function
所以我尝试模拟一个 jwt.verify 函数。下面是函数本身,然后是模拟。
try {
const decodedJwt = new Promise((resolve, reject) => {
jwt.verify(
token,
getPublicKey,
{
algorithms: ['RS256'],
ignoreExpiration: false,
},
(decodeError, decodedValue) => {
if (decodeError) {
reject(decodeError);
}
resolve(decodedValue);
}
);
});
return await decodedJwt;
} catch (error) {
logger.error(error);
return null;
}
验证部分的 Mock
export const jwtVerifyMock = jest.fn();
jest.mock('jsonwebtoken', () => {
return {
decode: jwtDecodeMock,
verify: jwtVerifyMock,
};
});
那么这就是我在测试中使用它的方式
it('decodeJWT should should verify token', async () => {
jwtVerifyMock.mockImplementation(async () => Promise.resolve({ exp: config.exp }));
return decodeJwt(config.jwtToken, true).then(async (value) => {
console.log('payload2', value);
const payload = value as Record<string, unknown>;
expect(payload.exp).toEqual(config.exp);
});
});
但由于某种原因,它没有得到解决。我得到一个
Async callback was not invoked within the 60000 ms timeout Error
我尝试使用 mockReturn 值,但效果不佳。所以接下来我猜测是作为回调传递给 jwt.verify 的 resolve 函数是我的问题所在。
您应该模拟 jwt.verify()
的实现并使用不同的参数手动执行回调函数。
例如
decode.ts
:
import jwt from 'jsonwebtoken';
export async function decode(token, getPublicKey) {
try {
const decodedJwt = new Promise((resolve, reject) => {
jwt.verify(
token,
getPublicKey,
{
algorithms: ['RS256'],
ignoreExpiration: false,
},
(decodeError, decodedValue) => {
if (decodeError) {
reject(decodeError);
}
resolve(decodedValue);
}
);
});
return await decodedJwt;
} catch (error) {
console.error(error);
return null;
}
}
decode.test.ts
:
import { decode } from './decode';
import jwt, { JsonWebTokenError } from 'jsonwebtoken';
describe('66966317', () => {
afterEach(() => {
jest.restoreAllMocks();
});
it('should decode value', async () => {
const decodedvalue = { name: 'teresa teng' };
const verifySpy = jest.spyOn(jwt, 'verify').mockImplementationOnce((token, getPublicKey, options, callback) => {
callback!(null, decodedvalue);
});
const actual = await decode('teresa teng', true);
expect(actual).toEqual({ name: 'teresa teng' });
expect(verifySpy).toBeCalledWith(
'teresa teng',
true as any,
{ algorithms: ['RS256'], ignoreExpiration: false },
expect.any(Function)
);
});
it('should handle decode error', async () => {
const decodedError = new JsonWebTokenError('network');
const verifySpy = jest.spyOn(jwt, 'verify').mockImplementationOnce((token, getPublicKey, options, callback) => {
callback!(decodedError, undefined);
});
const actual = await decode('teresa teng', true);
expect(actual).toBeNull();
expect(verifySpy).toBeCalledWith(
'teresa teng',
true as any,
{ algorithms: ['RS256'], ignoreExpiration: false },
expect.any(Function)
);
});
});
单元测试结果:
PASS examples/66966317/decode.test.ts (7.701 s)
66966317
✓ should decode value (3 ms)
✓ should handle decode error (17 ms)
console.error
JsonWebTokenError { name: 'JsonWebTokenError', message: 'network' }
23 | return await decodedJwt;
24 | } catch (error) {
> 25 | console.error(error);
| ^
26 | return null;
27 | }
28 | }
at Object.<anonymous> (examples/66966317/decode.ts:25:13)
at Generator.throw (<anonymous>)
at rejected (examples/66966317/decode.ts:1046:32)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
decode.ts | 100 | 100 | 100 | 100 |
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 8.749 s
所以我尝试模拟一个 jwt.verify 函数。下面是函数本身,然后是模拟。
try {
const decodedJwt = new Promise((resolve, reject) => {
jwt.verify(
token,
getPublicKey,
{
algorithms: ['RS256'],
ignoreExpiration: false,
},
(decodeError, decodedValue) => {
if (decodeError) {
reject(decodeError);
}
resolve(decodedValue);
}
);
});
return await decodedJwt;
} catch (error) {
logger.error(error);
return null;
}
验证部分的 Mock
export const jwtVerifyMock = jest.fn();
jest.mock('jsonwebtoken', () => {
return {
decode: jwtDecodeMock,
verify: jwtVerifyMock,
};
});
那么这就是我在测试中使用它的方式
it('decodeJWT should should verify token', async () => {
jwtVerifyMock.mockImplementation(async () => Promise.resolve({ exp: config.exp }));
return decodeJwt(config.jwtToken, true).then(async (value) => {
console.log('payload2', value);
const payload = value as Record<string, unknown>;
expect(payload.exp).toEqual(config.exp);
});
});
但由于某种原因,它没有得到解决。我得到一个
Async callback was not invoked within the 60000 ms timeout Error
我尝试使用 mockReturn 值,但效果不佳。所以接下来我猜测是作为回调传递给 jwt.verify 的 resolve 函数是我的问题所在。
您应该模拟 jwt.verify()
的实现并使用不同的参数手动执行回调函数。
例如
decode.ts
:
import jwt from 'jsonwebtoken';
export async function decode(token, getPublicKey) {
try {
const decodedJwt = new Promise((resolve, reject) => {
jwt.verify(
token,
getPublicKey,
{
algorithms: ['RS256'],
ignoreExpiration: false,
},
(decodeError, decodedValue) => {
if (decodeError) {
reject(decodeError);
}
resolve(decodedValue);
}
);
});
return await decodedJwt;
} catch (error) {
console.error(error);
return null;
}
}
decode.test.ts
:
import { decode } from './decode';
import jwt, { JsonWebTokenError } from 'jsonwebtoken';
describe('66966317', () => {
afterEach(() => {
jest.restoreAllMocks();
});
it('should decode value', async () => {
const decodedvalue = { name: 'teresa teng' };
const verifySpy = jest.spyOn(jwt, 'verify').mockImplementationOnce((token, getPublicKey, options, callback) => {
callback!(null, decodedvalue);
});
const actual = await decode('teresa teng', true);
expect(actual).toEqual({ name: 'teresa teng' });
expect(verifySpy).toBeCalledWith(
'teresa teng',
true as any,
{ algorithms: ['RS256'], ignoreExpiration: false },
expect.any(Function)
);
});
it('should handle decode error', async () => {
const decodedError = new JsonWebTokenError('network');
const verifySpy = jest.spyOn(jwt, 'verify').mockImplementationOnce((token, getPublicKey, options, callback) => {
callback!(decodedError, undefined);
});
const actual = await decode('teresa teng', true);
expect(actual).toBeNull();
expect(verifySpy).toBeCalledWith(
'teresa teng',
true as any,
{ algorithms: ['RS256'], ignoreExpiration: false },
expect.any(Function)
);
});
});
单元测试结果:
PASS examples/66966317/decode.test.ts (7.701 s)
66966317
✓ should decode value (3 ms)
✓ should handle decode error (17 ms)
console.error
JsonWebTokenError { name: 'JsonWebTokenError', message: 'network' }
23 | return await decodedJwt;
24 | } catch (error) {
> 25 | console.error(error);
| ^
26 | return null;
27 | }
28 | }
at Object.<anonymous> (examples/66966317/decode.ts:25:13)
at Generator.throw (<anonymous>)
at rejected (examples/66966317/decode.ts:1046:32)
-----------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-----------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 100 | 100 |
decode.ts | 100 | 100 | 100 | 100 |
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 8.749 s