测试结果不是恒定的。开个玩笑,测试库
The test results are not constant. in jest, testing-library
当我做纱线测试时,结果不断变化。
这是错误名称
“请求失败,状态代码为 400”
但我已经Api的请求功能已经在模拟
像这样
import * as api from '@api/user';
jest.mock('@api/user');
(api.fetchApiKeyUpdate as jest.Mock).mockImplementationOnce(() => {
throw { response: { data: { code: 'EX_INVALID_APIKEY_2015' } } };
});
(api.fetchApiKeyUpdate as jest.Mock).mockImplementationOnce(() => ({
status: 'success',
user: {
id: '99b1231230',
country: 'KR',
language: 'ko',
},
}));
由此做出的测试通过。但是测试经常失败。我不知道我应该怀疑什么。
export const fetchApiKeyUpdate = async ({
exchange,
apiKey,
secretKey,
passphrase,
otpCode,
}: ApiKeyUpdateRequest): Promise<UserInfoUpdateResponse | ApiAuthResponse> => {
const { data } = await axios.post(
apiKeyUpdateUrl,
{ apiKey, secretKey, passphrase, otpCode },
{ headers: { exchange } },
);
return data;
};
下面是我修改的部分代码
jest.mock('@api/user');
describe('API Register Success', () => {
const mockResponse = {
status: 'success',
user: {
id: '99bd10e123400',
userName: 't123st07',
receiveMarketingInfo: true,
},
};
beforeEach(() => {
(api.fetchApiKeyUpdate as jest.Mock).mockResolvedValueOnce(mockResponse);
});
it('키인증 성공시 아이콘 변경', async () => {
const { container } = render(
<ApiRegistrationBinanceTab
isOpen
handleOpenTab={jest.fn()}
/>,
);
userEvent.type(screen.getByPlaceholderText(/api key/i), 'apikey');
userEvent.click(screen.getByRole('button', { name: /Verify/i }));
await waitFor(() => {
expect(container.querySelector('#certified-icon')).toBeTruthy();
});
});
});
describe('API Register Fail', () => {
const mockResponse = { response: { data: { code: 'EX_INVALID_APIKEY_2015' } } };
beforeEach(() => {
(api.fetchApiKeyUpdate as jest.Mock).mockRejectedValueOnce(mockResponse);
});
it('remove input value if error code EX_INVALID_APIKEY_2015 or API_MANAGEMENT_ALREADY_REGISTERED', async () => {
render(
<ApiRegistrationBinanceTab
isOpen
handleOpenTab={jest.fn()}
/>,
);
userEvent.type(screen.getByPlaceholderText(/api key/i), 'apikey');
userEvent.click(screen.getByRole('button', { name: /Verify/i }));
await waitFor(() => {
expect(screen.getByPlaceholderText(/api key/i)).toHaveValue('');
});
});
});
FAIL src/components/articles/modal/custom/forgotPassword/ForgotPassword.spec.tsx
● 비밀번호 변경 스텝별로 진행
Request failed with status code 400
at createError (node_modules/axios/lib/core/createError.js:16:15)
at settle (node_modules/axios/lib/core/settle.js:17:12)
at XMLHttpRequest.handleLoad (node_modules/axios/lib/adapters/xhr.js:62:7)
at XMLHttpRequest.<anonymous> (node_modules/jsdom/lib/jsdom/living/helpers/create-event-accessor.js:32:32)
at innerInvokeEventListeners ...
我申请 beforeEach 并更改 mockimplementationOnce > mockResolvedValueOnce,mockRejectedValueOnce
但问题是随着页面(测试)的更改,故障会间歇性出现。
我对错误消息感到好奇的是...我在请求中模拟了一个函数(如 fetchAuthMail.. fetchApiKeyUpdate)。
所以我不知道为什么错误消息来自 axios,即使我认为我实际上并没有在测试中提出请求。
您不应使用 mockImplementation
,因为函数 return 是一个 Promise。
只需使用 mockResolvedValue
和 mockRejectedValue
使其 return 成为 Promise。
此外,您应该将模拟与一些 describe
分开(每个用例一个)并将模拟添加到 beforeAll
/ beforeEach
函数中。
就我个人而言,我刚刚对其进行了测试,我保留了你的@api/user.ts(我刚刚添加了 axios
导入),并且通过使用这些文件它起作用了(100% 起作用,从未失败):
index.ts
import * as api from '@api/user';
export const main = async () => {
const response = await api.fetchApiKeyUpdate({
exchange: 'fake-exchange',
apiKey: 'fake-apiKey',
secretKey: 'fake-secretKey',
passphrase: 'fake-passphrase',
otpCode: 'fake-otpCode',
});
return response.user;
};
index.spec.ts
import { main } from './index';
import * as api from '@api/user';
jest.mock('@api/user');
jest.mock('axios', () => ({
post: jest.fn().mockImplementation(() => {
console.error('axios should be mocked !'); // If some logs are shown, it means that one axios request was not mocked.
}),
}));
describe('UT main tests', () => {
describe('error', () => {
beforeEach(() => {
(api.fetchApiKeyUpdate as jest.Mock).mockRejectedValue({ response: { data: { code: 'EX_INVALID_APIKEY_2015' } } });
});
it('should rejects but not throw', async () => {
// Note that if you want to use .toThrow() method, you should set in mockRejectedValue an Error
await expect(main()).rejects.toStrictEqual({ response: { data: { code: 'EX_INVALID_APIKEY_2015' } } });
});
});
describe('error thrown', () => {
beforeEach(() => {
(api.fetchApiKeyUpdate as jest.Mock).mockRejectedValue(Error('FAKE ERROR'));
});
it('should rejects and throw', async () => {
// All working
await expect(main()).rejects.toThrow(Error);
await expect(main()).rejects.toThrowError('FAKE ERROR');
await expect(main()).rejects.toThrowError(Error('FAKE ERROR'));
});
});
describe('success', () => {
const mockResponse = {
status: 'success',
user: {
id: '99b1231230',
country: 'KR',
language: 'ko',
},
};
beforeEach(() => {
(api.fetchApiKeyUpdate as jest.Mock).mockResolvedValue(mockResponse);
});
it('should return user', async () => {
const response = await main();
expect(response).toStrictEqual(mockResponse.user);
});
});
});
编辑:我直接添加了一个 axios post 的模拟,你应该检查你的控制台上是否出现错误日志。如果是这样,则说明您忘记模拟一些 axios 调用。
当我做纱线测试时,结果不断变化。
这是错误名称 “请求失败,状态代码为 400”
但我已经Api的请求功能已经在模拟
像这样
import * as api from '@api/user';
jest.mock('@api/user');
(api.fetchApiKeyUpdate as jest.Mock).mockImplementationOnce(() => {
throw { response: { data: { code: 'EX_INVALID_APIKEY_2015' } } };
});
(api.fetchApiKeyUpdate as jest.Mock).mockImplementationOnce(() => ({
status: 'success',
user: {
id: '99b1231230',
country: 'KR',
language: 'ko',
},
}));
由此做出的测试通过。但是测试经常失败。我不知道我应该怀疑什么。
export const fetchApiKeyUpdate = async ({
exchange,
apiKey,
secretKey,
passphrase,
otpCode,
}: ApiKeyUpdateRequest): Promise<UserInfoUpdateResponse | ApiAuthResponse> => {
const { data } = await axios.post(
apiKeyUpdateUrl,
{ apiKey, secretKey, passphrase, otpCode },
{ headers: { exchange } },
);
return data;
};
下面是我修改的部分代码
jest.mock('@api/user');
describe('API Register Success', () => {
const mockResponse = {
status: 'success',
user: {
id: '99bd10e123400',
userName: 't123st07',
receiveMarketingInfo: true,
},
};
beforeEach(() => {
(api.fetchApiKeyUpdate as jest.Mock).mockResolvedValueOnce(mockResponse);
});
it('키인증 성공시 아이콘 변경', async () => {
const { container } = render(
<ApiRegistrationBinanceTab
isOpen
handleOpenTab={jest.fn()}
/>,
);
userEvent.type(screen.getByPlaceholderText(/api key/i), 'apikey');
userEvent.click(screen.getByRole('button', { name: /Verify/i }));
await waitFor(() => {
expect(container.querySelector('#certified-icon')).toBeTruthy();
});
});
});
describe('API Register Fail', () => {
const mockResponse = { response: { data: { code: 'EX_INVALID_APIKEY_2015' } } };
beforeEach(() => {
(api.fetchApiKeyUpdate as jest.Mock).mockRejectedValueOnce(mockResponse);
});
it('remove input value if error code EX_INVALID_APIKEY_2015 or API_MANAGEMENT_ALREADY_REGISTERED', async () => {
render(
<ApiRegistrationBinanceTab
isOpen
handleOpenTab={jest.fn()}
/>,
);
userEvent.type(screen.getByPlaceholderText(/api key/i), 'apikey');
userEvent.click(screen.getByRole('button', { name: /Verify/i }));
await waitFor(() => {
expect(screen.getByPlaceholderText(/api key/i)).toHaveValue('');
});
});
});
FAIL src/components/articles/modal/custom/forgotPassword/ForgotPassword.spec.tsx
● 비밀번호 변경 스텝별로 진행
Request failed with status code 400
at createError (node_modules/axios/lib/core/createError.js:16:15)
at settle (node_modules/axios/lib/core/settle.js:17:12)
at XMLHttpRequest.handleLoad (node_modules/axios/lib/adapters/xhr.js:62:7)
at XMLHttpRequest.<anonymous> (node_modules/jsdom/lib/jsdom/living/helpers/create-event-accessor.js:32:32)
at innerInvokeEventListeners ...
我申请 beforeEach 并更改 mockimplementationOnce > mockResolvedValueOnce,mockRejectedValueOnce
但问题是随着页面(测试)的更改,故障会间歇性出现。
我对错误消息感到好奇的是...我在请求中模拟了一个函数(如 fetchAuthMail.. fetchApiKeyUpdate)。
所以我不知道为什么错误消息来自 axios,即使我认为我实际上并没有在测试中提出请求。
您不应使用 mockImplementation
,因为函数 return 是一个 Promise。
只需使用 mockResolvedValue
和 mockRejectedValue
使其 return 成为 Promise。
此外,您应该将模拟与一些 describe
分开(每个用例一个)并将模拟添加到 beforeAll
/ beforeEach
函数中。
就我个人而言,我刚刚对其进行了测试,我保留了你的@api/user.ts(我刚刚添加了 axios
导入),并且通过使用这些文件它起作用了(100% 起作用,从未失败):
index.ts
import * as api from '@api/user';
export const main = async () => {
const response = await api.fetchApiKeyUpdate({
exchange: 'fake-exchange',
apiKey: 'fake-apiKey',
secretKey: 'fake-secretKey',
passphrase: 'fake-passphrase',
otpCode: 'fake-otpCode',
});
return response.user;
};
index.spec.ts
import { main } from './index';
import * as api from '@api/user';
jest.mock('@api/user');
jest.mock('axios', () => ({
post: jest.fn().mockImplementation(() => {
console.error('axios should be mocked !'); // If some logs are shown, it means that one axios request was not mocked.
}),
}));
describe('UT main tests', () => {
describe('error', () => {
beforeEach(() => {
(api.fetchApiKeyUpdate as jest.Mock).mockRejectedValue({ response: { data: { code: 'EX_INVALID_APIKEY_2015' } } });
});
it('should rejects but not throw', async () => {
// Note that if you want to use .toThrow() method, you should set in mockRejectedValue an Error
await expect(main()).rejects.toStrictEqual({ response: { data: { code: 'EX_INVALID_APIKEY_2015' } } });
});
});
describe('error thrown', () => {
beforeEach(() => {
(api.fetchApiKeyUpdate as jest.Mock).mockRejectedValue(Error('FAKE ERROR'));
});
it('should rejects and throw', async () => {
// All working
await expect(main()).rejects.toThrow(Error);
await expect(main()).rejects.toThrowError('FAKE ERROR');
await expect(main()).rejects.toThrowError(Error('FAKE ERROR'));
});
});
describe('success', () => {
const mockResponse = {
status: 'success',
user: {
id: '99b1231230',
country: 'KR',
language: 'ko',
},
};
beforeEach(() => {
(api.fetchApiKeyUpdate as jest.Mock).mockResolvedValue(mockResponse);
});
it('should return user', async () => {
const response = await main();
expect(response).toStrictEqual(mockResponse.user);
});
});
});
编辑:我直接添加了一个 axios post 的模拟,你应该检查你的控制台上是否出现错误日志。如果是这样,则说明您忘记模拟一些 axios 调用。