使用提取API测试Redux登录操作

时间:2019-06-17 09:53:07

标签: javascript unit-testing react-native testing redux

在我的React-Native项目上,我尝试开始单元测试,如何测试涉及登录提取api调用的Redux动作。我看过一些测试异步Action的示例,但是我没有包装我围绕如何测试下面的代码。

我已经看过使用redux-mock-store,但是我不知道从哪里开始测试。

import {
  API_URL_AUTH,
  API_URL,
  CLIENT_ID,
  CLIENT_SECRET,
} from "../config/consts";

import { FETCHING, FETCHED } from "../actions/ActionTypes";

const { dispatch } = this.props;
const { email, password } = this.state;

const authenticationData = {
  client_id: CLIENT_ID,
  client_secret: CLIENT_SECRET,
  grant_type: "password",
  username: email,
  password: password,
};

dispatch({ type: FETCHING });

let response = await (await fetch(API_URL_AUTH + "oauth/token", {
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json",
  },
  method: "POST",
  body: JSON.stringify(authenticationData),
})).json();

if (!response.error) {
  await AsyncStorage.setItem("accessToken", "Bearer " + response.access_token);
  let user = await (await fetch(API_URL + "user", {
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
      Authorization: "Bearer " + response.access_token,
    },
    method: "GET",
  })).json();
} else {
  showMessage({
    message: response.message,
    type: "danger",
  });
}

dispatch({ type: FETCHED });

1 个答案:

答案 0 :(得分:0)

简介

我第一次积极回答关于stackoverflow的问题时,我必须注册一个帐户,但是事情就这样了。

单元测试的还原动作完全是关于测试协作的。将协作“单元”测试与每个人都知道的简单的简单单元测试分开总是很聪明的。

先清理

我首先将fetch和locale存储调用抽象到它们自己的包装函数中。这有几个优点:

  • 更易于测试(协作功能AKA测试不应调用太多逻辑,而只是调用其他功能)
  • 您可以控制该api(易于交换库)
// api.js
import {
  API_URL_AUTH,
  API_URL,
  CLIENT_ID,
  CLIENT_SECRET,
} from "../config/consts";

const authenticationData = {
  client_id: CLIENT_ID,
  client_secret: CLIENT_SECRET,
  grant_type: "password",
};

export const fetchToken = ({ username, password }) => {
  return fetch(API_URL_AUTH + "oauth/token", {
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
    },
    method: "POST",
    body: JSON.stringify({ ...authenticationData, username, password }),
  })).json()
}

export fetchUser = token => fetch(API_URL + "user", {
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json",
    Authorization: "Bearer " + token,
  },
  method: "GET",
})).json();

// localstorage.js
// import { AsyncStorage } from 'some-library' ???
export const storeItem = (key, value)=> AsyncStorage.setItem(key, value);

这使动作的代码更加清晰,并且您想要完成的工作更加直接,最终将使测试变得更容易。

// actions.js
import { fetchToken, fetchUser } from "./api";
import { storeItem } from "./localstorage";
import { FETCHING, FETCHED } from "../actions/ActionTypes";

export const loginUser = ({ username, password }) => async (
  dispatch,
  getState,
  { signInUser, getCurrentUser }
) => {
  dispatch({ type: FETCHING }); // probably needs a better action type

  try {
    const response = await fetchToken({ username, password });

    if (!response.error) {
      await storeItem ("accessToken", "Bearer " + response.access_token);
      await fetchUser(response.access_token)
    } else {
      showMessage({
        message: response.message,
        type: "danger",
      });
    }

    dispatch({ type: FETCHED }); // needs better action type
  } catch (e) {
    showMessage({
      message: response.message,
      type: "danger",
    });
  }
}

Da测试

请注意,(我相信)Redux中的动作是协作者测试,这意味着它们非常适合模拟功能,因为您仅测试交互,而不是功能的实际逻辑。简单的逻辑函数很容易进行单元测试,包装库的函数(因此您可以控制api)通常根本不会经过测试,或者您可以编写几个集成测试,这些测试独立地测试包装器,但与库本身。

您会看到,通过提取逻辑,动作本身变得非常简单,因此易于测试。

在我使用的testdouble库中要注意的一件事是td.when也验证了该调用。因此,如果您在代码中无意中调用了fetchToken({ email, password })之类的东西,则测试将失败的原因有两个:

    用错误的参数调用了
  1. fetchToken
  2. thenResolve不会返回包含{ access_token: 'token123' }的诺言,这意味着fetchUser也不会使用正确的参数来调用,因为access_token将是{{1} }
undefined

结束语

我在github上有一个要点,这是同一原理的另一个示例,因为对于React不和谐的人们来说这是一个常见问题。 您可以在这里找到一个:https://gist.github.com/venikx/6e03367300f47625d5373826e86afeae

我建议您看看https://github.com/testdouble/contributing-tests/wiki/Test-Double,它是测试的绝佳资源

看看https://www.youtube.com/watch?v=Af4M8GMoxi4,它更深入地解释了这些协作类型的测试(有关包装函数,简单逻辑函数以及它们应如何与这些协作函数进行交互的讨论)

关于测试的最重要部分是隔离在重构某些代码时不应中断的行为。测试应该使您可以轻松地重构代码,而不是更难(这就是为什么我们喜欢包装器函数的原因)。

希望对您有所帮助。现在我回到潜伏的^^