我正在使用 React 和 RTK Query 并尝试编写测试,检查正确的下载文件,使用 jest 和 jest-fetch-mock。
test('should download correct file', async () => {
const text = '<template>some template</template>>'
const testBlob = new Blob([text]);
render(<DownloadButton/>);
const mockedCreateObjectURL = jest.fn();
const mockedRevokeObjectURL = jest.fn();
global.URL.createObjectURL = mockedCreateObjectURL;
global.URL.revokeObjectURL = mockedRevokeObjectURL;
const buttonElem = screen.getByText('Download');
await userEvent.click(buttonElem);
expect(mockedCreateObjectURL).toBeCalled();
expect(mockedCreateObjectURL).toBeCalledWith(testBlob);
})
测试成功,但不正确,我可以用另一个Blob替换testBlob,并且将测试成功。
另外,我的控制台出现错误
A non-serializable value was detected in an action, in the path: `payload`. Value: Blob {
[Symbol(type)]: 'application/octet-stream',
[Symbol(buffer)]: <Buffer 5b 6f 62 6a 65 63 74 20 42 6c 6f 62 5d>
}
Take a look at the logic that dispatched this action: {
type: 'rtkQueryApi/executeQuery/fulfilled',
payload: Blob {
[Symbol(type)]: 'application/octet-stream',
[Symbol(buffer)]: <Buffer 5b 6f 62 6a 65 63 74 20 42 6c 6f 62 5d>
},
meta: {
fulfilledTimeStamp: 1721133765208,
baseQueryMeta: { request: [Request], response: [Response] },
RTK_autoBatch: true,
arg: {
type: 'query',
subscribe: true,
forceRefetch: true,
subscriptionOptions: [Object],
endpointName: 'getTerminalGroupCertificatesConfig',
originalArgs: 100,
queryCacheKey: 'getTerminalGroupCertificatesConfig(100)',
[Symbol(forceQueryFn)]: undefined
},
requestId: 'VJioDWBB5c0uoj69n4iMP',
requestStatus: 'fulfilled'
}
}
如何使用 jest-fetch-mock 纠正模拟 Blob 响应
尝试使用 jest-fetch-mock 来模拟 Blob 的响应,但不正确
当前测试通过,因为它仅检查 createObjectURL 是否被调用,但不验证 Blob 的内容。此外,您看到的错误是由于 RTK 查询尝试序列化不可序列化的 Blob 对象所致。
以下是修改测试的方法:
import { enableFetchMocks } from 'jest-fetch-mock';
enableFetchMocks();
test('should download correct file', async () => {
const text = '<template>some template</template>';
const testBlob = new Blob([text], { type: 'text/html' });
const mockUrl = 'blob:http://localhost/some-fake-url';
// Mock fetch to return the Blob
fetchMock.mockResponse(() => Promise.resolve({
body: testBlob,
}));
render(<DownloadButton />);
const mockedCreateObjectURL = jest.fn(() => mockUrl);
const mockedRevokeObjectURL = jest.fn();
global.URL.createObjectURL = mockedCreateObjectURL;
global.URL.revokeObjectURL = mockedRevokeObjectURL;
const buttonElem = screen.getByText('Download');
await userEvent.click(buttonElem);
expect(mockedCreateObjectURL).toHaveBeenCalledWith(testBlob);
expect(mockedCreateObjectURL).toReturnWith(mockUrl);
});
确保您的 jest-fetch-mock 使用正确的 Blob 内容正确模拟 fetch 响应。
考虑将 Blob 转换为 URL 或 base64 字符串,然后再将其传递到任何 Redux 操作或 RTK 查询。