首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Jest和app测试React

使用Jest和app测试React
EN

Stack Overflow用户
提问于 2017-02-15 20:52:24
回答 2查看 1.7K关注 0票数 4

我好像搞不明白这件事。我使用创建-反应-应用程序,它是内置于测试运行Jest。对于所有同步代码来说,它似乎运行得很好,但是当嘲笑承诺时,我似乎无法让它工作起来。

react组件有一个表单,我可以模拟提交。

响应组件代码段。

代码语言:javascript
复制
//Top of the page
import {auth} from '../../lib/API_V2'
// ... //

// Handle submit runs when the form is submitted
handleSubmit = (event) => {
  console.log('submit')
  event.preventDefault()
  this.setState(prevState => ({
    ...prevState,
    loading: true
  }))
  console.log('stateSet')
  auth(this.state.userName, this.state.password)
    .then(results => {
      // NEVER RUNS
      console.log('then')
      // stuff omitted
      this.setState(prevState => ({
        ...prevState,
        loading: false
      }))
      this.props.afterAuth()
    })
  .catch(() => {
    // also never runs
    // omitted
    this.setState(prevState => ({
      ...prevState,
      loading: false
    }))
    this.props.afterAuth()
  })
}

测试代码

代码语言:javascript
复制
jest.mock('../../lib/API_V2')
it.only(`should mock a login`, () => {
  const myMock = jest.fn()
  const authComp = mount(<AuthComponent afterAuth={myMock}/>)

  authComp.find('.userName').simulate('change', {target: {value: 'userName'}})
  authComp.find('.password').simulate('change', {target: {value: 'password'}})
  expect(authComp.state().userName).toEqual('userName')
  expect(authComp.state().password).toEqual('password')
  authComp.find('[type="submit"]').get(0).click()
  expect(myMock.mock.calls.length).toBe(1) // FAILS
})

API库返回一个承诺。我没有使用它,而是在它旁边有一个__mocks__/API_V2.js。看上去像这样

代码语言:javascript
复制
function auth (lastname, accountNumber) {
  console.log('yay!?')
  return new Promise((resolve) => {
    resolve({
      accountNumber,
      lastName: lastname
    })
  })
}     

我的模拟测试代码似乎从未运行过。如果我记录了模拟函数,就会得到function auth() {return mockConstructor.apply(this,arguments);}

我尝试遵循https://facebook.github.io/jest/docs/tutorial-async.html的指令,但似乎没有调用我的模拟方法。而实际的方法也是如此。相反,我对auth()的调用返回未定义的。

有人有什么想法吗?

-补充资料--

代码语言:javascript
复制
src
  Components
    AuthComponent
      AuthComponent.js
      AuthComponent.test.js
      index.js
  Lib
    API_V2
      API_V2.js
      index.js
      __mocks__
        API_V2.js
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-02-16 00:17:18

我认为你碰到了一个与这个问题相关的bug:https://github.com/facebook/jest/issues/2070

由于您实际上试图导入一个名为API_V2/index.js的文件,所以需要模拟index.js。但是,这样做将非常困难,因为它将是您试图模拟的每个index.js文件的有效模拟。

目前最好的方法是重写一些代码,以使用依赖注入,并将模拟传递给任何需要使用{ auth }的代码。

票数 3
EN

Stack Overflow用户

发布于 2017-02-16 02:07:09

在模拟的新承诺中,即使您立即解决,此解析也不会同步发生。承诺回调总是作为一个排队的微任务运行,所以当您在测试中模拟单击时,模拟中的承诺回调还没有运行(因此myMock也还没有被调用)。这就是你的期望失败的原因。

解决这个问题的一种(有点麻烦的)方法是使用setTimeout。setTimeout将为任务排队,任务总是在微任务之后运行。Jest通过从it回调返回承诺来支持异步测试,因此您可以编写:

代码语言:javascript
复制
jest.mock('../../lib/API_V2')
it.only(`should mock a login`, () => new Promise(resolve => {
  const myMock = jest.fn()
  const authComp = mount(<AuthComponent afterAuth={myMock}/>)

  authComp.find('.userName').simulate('change', {target: {value: 'userName'}})
  authComp.find('.password').simulate('change', {target: {value: 'password'}})
  expect(authComp.state().userName).toEqual('userName')
  expect(authComp.state().password).toEqual('password')
  authComp.find('[type="submit"]').get(0).click()
  setTimeout(() => {
    expect(myMock.mock.calls.length).toBe(1)
    resolve() // Tell jest this test is done running
  }, 0);
}))

这里很好地解释了任务和微任务是如何工作的:https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42259825

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档