【问题标题】:mock service worker, sad path test failure模拟服务人员,悲伤的路径测试失败
【发布时间】:2022-01-13 15:58:45
【问题描述】:

最近只是使用 Mock Service Worker 来测试我的 HTTP 请求,我正在寻找测试我的失败路径。

我的第一个测试通过(很高兴),但我收到的错误是“JSON 输入意外结束”

它确实以我想要的方式运行,但从测试的角度来看,我有点困惑。

我怎样才能让我的失败路径通过测试?

我的测试文件

import "whatwg-fetch";
import { rest } from "msw";
import { setupServer } from "msw/node";

import { collect } from "./collect";

const server = setupServer(
  rest.get(
    "http://api.openweathermap.org/data/2.5/weather",
    (req, res, ctx) => {
      return res(
        ctx.status(200),
        ctx.json({ base: "stations", clouds: { all: 6 }, cod: 200 })
      );
    }
  )
);

beforeAll(() => server.listen());
afterAll(() => server.close());
afterEach(() => server.resetHandlers());

it("collects data", async () => {
  const res = await collect();
  expect(res).toEqual({ base: "stations", clouds: { all: 6 }, cod: 200 });
});

it("handles failure", async () => {
  server.use(
    rest.get(
      "http://api.openweathermap.org/data/2.5/weather",
      (req, res, ctx) => {
        return res(ctx.status(401));
      }
    )
  );
  await expect(collect()).rejects.toThrow("401");
});

我的 fetch 异步函数

require('dotenv').config()

export const collect = async () => {
    const key = process.env.REACT_APP_API_KE
    // try{
      const res = await fetch(`http://api.openweathermap.org/data/2.5/weather?q=london&appid=${key}`)
      if(res.status !== 200){
        const error = await res.json()
        throw { message: error.message, status: error.cod }
      }
        const data = await res.json()
        return data 
}

【问题讨论】:

  • 请修改您的帖子标题,以句子形式提出一个清晰、具体的问题。见How to Ask

标签: javascript reactjs api testing msw


【解决方案1】:

修复模拟服务器

问题是collect 函数即使在出现错误的情况下也期待 JSON 响应,但您的模拟服务器不会返回该响应。因此,当您在 collect 函数中执行 res.json() 时,您会收到错误。

更新您的响应解析器以返回 json 响应。

return res(ctx.json({message: "error"}), ctx.status(401));

修复测试

toThrow 在这里不是正确的匹配器,因为 async 函数总是返回承诺,而在您的情况下,collect 函数返回一个承诺,该承诺被抛出的数据拒绝。
因此,您可以改用toEqual 匹配器。

您还需要更新测试错误的方式。您可以选择以下任一选项:

使用rejects匹配器:

it("handles failure", () => {
  server.use(
    rest.get(
      "http://api.openweathermap.org/data/2.5/weather",
      (req, res, ctx) => {
        return res(ctx.json({message: "error"}), ctx.status(401));
      }
    )
  );
  return expect(collect()).rejects.toEqual({ message: "error", status: 401 });
});

使用async/await 语法:

it("handles failure", async () => {
  server.use(
    rest.get(
      "http://api.openweathermap.org/data/2.5/weather",
      (req, res, ctx) => {
        return res(ctx.status(401));
      }
    )
  );
  try {
    await collect();
  } catch (err) {
    expect(err).toEqual({ message: "error", status: 401 });
  }
});

使用.catch

但在这种方法中,您需要明确检查您的 catch 断言是否已被调用,否则已履行的承诺不会使您的测试失败。

it("handles failure", async () => {
  server.use(
    rest.get(
      "http://api.openweathermap.org/data/2.5/weather",
      (req, res, ctx) => {
        return res(ctx.status(401));
      }
    )
  );
  expect.assertions(1);
  return collect().catch((err) =>
    expect(err).toEqual({ message: "error", status: 401 })
  );
});

修复collect 函数

在您的 collect 函数中,status 应该是 res.status 而不是 data.code

您还可以通过将res.json() 调用移出条件来稍微清理一下以下代码。

require("dotenv").config();

export const collect = async () => {
  const key = process.env.REACT_APP_API_KEY;
  const res = await fetch(
    `http://api.openweathermap.org/data/2.5/weather?q=london&appid=${key}`
  );
  const data = await res.json();
  if (res.status !== 200) {
    throw { message: data.message, status: res.status };
  }
  return data;
};

而且你不应该在反应环境变量中存储秘密,否则会暴露。 Docs

【讨论】:

  • 感谢您的建议,不幸的是我仍然收到Received message: "Unexpected end of JSON input" 这是因为我使用的是从 API 收到的错误消息,而不是错误对象吗?
  • 我已经更新了我的答案,你能看看这是否解决了你的问题@fluffy-lionz?
  • 另外,问题不是因为您使用的是从服务器收到的错误消息,它完全没问题。问题是您的模拟服务器与您的实际服务器不同。如果实际服务器返回错误消息,那么模拟服务器也应该返回。希望这是有道理的!
  • 啊,好吧,我玩过它,我的新失败是Received function did not throw
  • 真的很接近,我要做的就是将我的 throw 对象中的状态值更改为响应状态` if (res.status !== 200) { throw { message: data .message,状态:res.status }; } ` 测试正在进行中,感谢您的帮助
【解决方案2】:

在一些帮助下,我更新了收集功能,如下所示 我现在将响应的值作为状态发送

require("dotenv").config();

export const collect = async () => {
  const key = process.env.REACT_APP_API_KEY;
  const res = await fetch(
    `http://api.openweathermap.org/data/2.5/weather?q=london&appid=${key}`
  );
  const data = await res.json();
  if (res.status !== 200) {
    throw { message: data.message, status: res.status };
  }
  return data;
};

我的测试现在看起来像这样,我必须使用 toEqual 匹配器而不是 toThrow 并让它返回而不是 await / async

it("handles failure", () => {
  server.use(
    rest.get(
      "http://api.openweathermap.org/data/2.5/weather",
      (req, res, ctx) => {
        return res(ctx.json({message: "error"}), ctx.status(401));
      }
    )
  );
  return expect(collect()).rejects.toEqual({ message: "error", status: 401 });
});

【讨论】:

    猜你喜欢
    • 2021-08-26
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 2020-12-04
    • 2021-12-25
    • 2020-01-05
    • 2018-02-14
    • 1970-01-01
    相关资源
    最近更新 更多