如何使用 jest 和 jest-fetch-mock 来模拟 Blob

问题描述 投票:0回答:1

我正在使用 React 和 RTK Query 并尝试编写测试,检查正确的下载文件,使用 jestjest-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 的响应,但不正确

reactjs testing jestjs blob jest-fetch-mock
1个回答
0
投票

当前测试通过,因为它仅检查 createObjectURL 是否被调用,但不验证 Blob 的内容。此外,您看到的错误是由于 RTK 查询尝试序列化不可序列化的 Blob 对象所致。

  • 使用 jest-fetch-mock 模拟 fetch 响应并直接返回 Blob。这允许您控制 Blob 的内容并确保创建正确的 Blob。
  • 由于 RTK Query 抱怨不可序列化的 Blob,因此您应该避免将 Blob 本身置于 Redux 状态。相反,返回 URL 或文件的其他可序列化表示形式。您可以在存储之前将 Blob 转换为 URL。

以下是修改测试的方法:

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 查询。

© www.soinside.com 2019 - 2024. All rights reserved.