用 Jest 反应单元测试 - 模拟 localStorage 的问题

Posted

技术标签:

【中文标题】用 Jest 反应单元测试 - 模拟 localStorage 的问题【英文标题】:React unit test with Jest - issue on simulating localStorage 【发布时间】:2018-12-28 13:56:24 【问题描述】:

我在对简单组件进行单元测试时遇到了问题(这里更加简化了):

import React,  Component  from 'react';
import Logout from '../auth/Logout';
import  logoutUser  from '../../actions/auth';

export default class Navbar extends Component 

  render() 
    const  dispatch, isAuthenticated  = this.props;

    if (isAuthenticated) 
      logStatus = <Logout onLogoutClick=() => dispatch(logoutUser()) />;
     else 
      logStatus = (
        <Link to="/login/">
          <Button>Login</Button>
        </Link>
      );
    

    return (
      <AppBar>        
        logStatus
      </AppBar>
    );
  

import logoutUser from '../../actions/auth'; 我在localStorage 上有一个函数 removeItem。我不会将它用于我的测试,但这就是我有错误的地方。

我的测试是:

test('Navbar test series', () => 
  //Enzyme testing
  it('show the login button', () => 
    const wrapper = shallow(<Navbar isAuthenticated=true />);
    expect(wrapper.find(Login)).to.have.length(1);
  );
);

我明白了:

ReferenceError: localStorage is not defined      
      at Object.<anonymous> (src/axios/axios.js:8:15) [I don't know why this is here...]
      at Object.<anonymous> (src/actions/auth.js:89:38) [my logoutUser using localStorage is here ]
      at Object.<anonymous> (src/components/UI/Navbar.js:3:13)
      at Object.<anonymous> (src/components/UI/Navbar.test.js:2:15)

像这里建议的那样做How do I deal with localStorage in jest tests?:

var localStorageMock = (function ()  [...])();
Object.defineProperty(window, 'localStorage',  value: localStorageMock );

没有帮助。

我不明白的是我什至没有打电话给dispatch(logoutUser()) 那么为什么要尝试访问 localStorage 呢?问题是由于 redux through dispatch 引起的吗?

非常感谢您的帮助!

编辑1: 注销组件:

import React from 'react';
import Button from '@material-ui/core/Button';

const Logout = props => (
  <Button onClick=() => props.onLogoutClick()     color="secondary">LOGOUT</Button>
);

export default Logout;

以及来自 actions/auth.js 和 logoutUser() 的代码:

export function logoutUser() 
  return dispatch => 
    dispatch(requestLogout());
    localStorage.removeItem('token');
    dispatch(receiveLogout());
  ;

【问题讨论】:

How do I deal with localStorage in jest tests?的可能重复 我不这么认为,我尝试使用您链接的帖子“模拟”localStorage,但它没有改变。我认为问题更多在于为什么首先调用这个 logoutUser 函数? 你能把Logout组件的代码贴出来吗? 完成,我添加了注销组件。非常非常简单。 我发现我只是通过导入我的组件就出现了这个错误。即使没有变浅......奇怪,我会挖掘它。 【参考方案1】:

您可以添加测试文件

global.localStorage = 
    getItem: () => undefined,
;

test('Navbar test series', () => 
  //Enzyme testing
  it('show the login button', () => 
    const wrapper = shallow(<Navbar isAuthenticated=true />);
    expect(wrapper.find(Login)).to.have.length(1);
  );
);

【讨论】:

再一次,我已经尝试使用这个精确的 sn-p 来模拟 localStorage ***.com/a/32911774/1565738,这不是这里的问题。无论如何谢谢:) 完成,我已经从 auth.js 添加了 logoutUser() 函数【参考方案2】:

您是否尝试过完全为该测试模拟 ../../actions/auth

jest.setMock('../../actions/auth', () => ( logoutUser: jest.fn() ))

【讨论】:

我刚试过,我仍然被那个 localStorage 错误阻止:) 不过这是个好主意! 有点离题,但你应该试试react-testing-library。浅渲染是一种真正的痛苦。在我的测试中,我用global.localStorage = setItem: jest.fn() ; 模拟localStorage,它就成功了。希望你能找到解决办法!【参考方案3】:

所以解决方案是:

      at Object.<anonymous> (src/axios/axios.js:8:15) [I don't know why this is here...]

我在运行时使用 localstorage 找到了一个 const。只要把它放在一个条件下,它就解决了这个问题。

感谢大家的努力,这是我的错误:-(

【讨论】:

但是为什么没有调用模拟实现呢?您是通过 window.localstorage 还是其他方式引用它? 因为 const token = localStorage.get[...] 是在我的 axios/axios.js 的根目录中调用的,因此调用了 import 链。所以在 localStorage 的模拟实现之前。 即使我在第一行使用模拟测试过一次,但我想我做得很糟糕......

以上是关于用 Jest 反应单元测试 - 模拟 localStorage 的问题的主要内容,如果未能解决你的问题,请参考以下文章

用 Jest 模拟 Firebase 功能(单元测试)

用 Jest 模拟基于承诺的请求

用 Jest 模拟 Lerna 范围模块

带有笑话和酶的反应单元测试

模拟安装挂钩 Jest 测试单元

如何使用 Jest 和 Enzyme 对包含 history.push 的反应事件处理程序进行单元测试?