如何测试redux-saga的调用外部api的生成器?

时间:2019-09-15 23:07:15

标签: javascript reactjs redux jestjs redux-saga

在编写测试时,我是一个完全的初学者,但是我已经获得了测试一些api实现的任务,这是使用redux和redux-saga完成的。场景是用户用其用户名,密码填写准备好的表单,而我的生成器函数“ authenticateUser”从api调用正确的端点(api处理程序是从Swagger自动生成的,并从私有注册表导入),以创建令牌并检查用户是否存在在数据库中。如果是这样,令牌将保存到会话/本地存储中,并使用相应的值更新存储。


import { userAuthenticated, userAuthenticationRejected } from "../actions/user";
import { call, put } from "redux-saga/effects";
import createApi from "@my-module";

export function* authenticateUser(action) {
  const myApi = yield call(createApi, {
    cors: true,
    securityHandlers: {
      Basic: () => true,
      Bearer: () => true
    }
  });

  try {
    const response = yield call(myApi.token_create, {
      data: {
        username: action.payload.username,
        password: action.payload.password
      }
    });
    if (response.status === 200) {
      const body = yield call([response, "json"]);
      const accessToken = body.access;
      window.sessionStorage.setItem("accessToken", accessToken);
      if (action.payload.persistAuthenticationToken) {
        window.localStorage.setItem("accessToken", accessToken);
      }

      yield put(
        userAuthenticated({
          username: action.payload.username,
          accessToken
        })
      );
    } else {
      throw new Error("Unauthorized");
    }
  } catch (error) {
    yield put(userAuthenticationRejected());
  }
}

在阅读有关测试方法时,我完全迷失了。我已经尝试过使用连续的“ generator.next()。value”进行简单的单元测试,但是在第一次屈服之后,它甚至无法进入“ try”块并比预期更快地抛出“ undefined”。

test("User authentication", () => {
  const action = {
    payload: {
      username: "test",
      password: "test"
    }
  };
  const generator = cloneableGenerator(authenticateUser)(action);
  console.log(generator.next().value);

  // {
  //   '@@redux-saga/IO': true,
  //   combinator: false,
  //   type: 'CALL',
  //   payload: {
  //     context: null,
  //     fn: [Function: createApi],
  //     args: [ [Object] ]
  //   }
  // }

  console.log(generator.next().value);

  // {
  //   '@@redux-saga/IO': true,
  //   combinator: false,
  //   type: 'PUT',
  //   payload: {
  //     channel: undefined,
  //     action: { type: 'USER_AUTHENTICATION_REJECTED' }
  //   }
  // }

  console.log(generator.next().value);

  // undefined

});

当我看集成测试时,这似乎是首选方法,我不能只是将相对简单的示例转移到我的特定案例中。

我将不胜感激,因为我只是不知道从哪里开始。

1 个答案:

答案 0 :(得分:1)

您需要为响应对象传递一个模拟值。我假设它是未定义的,并且response.status的值不是200时,您的代码将抛出。因此,对于您自己,一次对generator.next().value的调用传递的模拟是这样的:

const responseMock = {
    status: 200,
     // anything else it needs
}
console.log(generator.next(reponseMock).value)