我如何用笑话来测试基于承诺的代码?

时间:2018-10-06 01:50:57

标签: javascript promise jestjs

我该如何开玩笑地测试此代码?我想确保已根据需要调用已通过承诺的错误和成功。我敢肯定这有点简单,但是却让我发疯。非常感谢。

handleStatusChangeRequest (changeEntryStatus) {
  return changeEntryStatus().then(() => {
    this.handleStatusChangeSuccess()
  }).catch(err => {
    this.handleErrorDisplay(err)
  })
}

4 个答案:

答案 0 :(得分:0)

如果您的代码使用promise,则有一种不错的方式来处理异步测试。只需从测试中返回一个promiseJest将等待该promise解析。
如果诺言被拒绝,则测试将自动失败。

例如,假设changeData而不是使用回调,而是返回一个promise,该解析应该解析为字符串“状态已成功修改”

请确保 return promise-如果省略此return语句,则测试将在changeData()-[ async函数”之前完成]完成。

这是一种方便易用的模式

test('if the data is changed', () => {
  return changeData().then((data) => {
    expect(data).toBe('status has been successfully modified');
  });
})

测试愉快:)

答案 1 :(得分:0)

这可以重构,但是为了演示起见,我保留了重复的位。

example.spec.js中,回调changeEntryStatus被存根以返回承诺。为了检查是否调用了其他实例方法(this.method),首先对它们进行了模拟,然后在运行被测试的方法后在模拟上调用断言。在Jest docs中了解更多信息。 (请参阅我对底部所测试单元的模拟方法的看法。)

Run the example on repl.it.

example.js:

class Example {
  handleStatusChangeRequest(changeEntryStatus) {
    return changeEntryStatus().then(() => {
      this.handleStatusChangeSuccess()
    }).catch(err => {
      this.handleErrorDisplay(err)
    })
  }

  handleStatusChangeSuccess() {
    console.log('stubbed handleStatusChangeSuccess')
  }

  handleErrorDisplay(error) {
    console.log('stubbed handleErrorDisplay:', error)
  }
}

module.exports = Example;

example.spec.js:

const Example = require('./entryStatus')
describe('handleStatusChangeRequest', () => {
  it('should run the changeEntryStatus callback', () => {
    const {handleStatusChangeRequest} = new Example()
    const stub = jest.fn().mockResolvedValue()

    handleStatusChangeRequest(stub)

    // must return because handleStatusChangeRequest is asynchronous
    return expect(stub).toHaveBeenCalled()
  });

  it('should call example.handleStatusChangeSuccess', async () => {
    const example = new Example()
    const stub = jest.fn().mockResolvedValue()
    example.handleStatusChangeSuccess = jest.fn()

    await example.handleStatusChangeRequest(stub)

    expect(example.handleStatusChangeSuccess).toHaveBeenCalled();
  })

  it('should call example.handleErrorDisplay', async () => {
    const example = new Example()
    const fakeError = { code: 'fake_error_code' }
    const stub = jest.fn().mockRejectedValue(fakeError)
    example.handleErrorDisplay = jest.fn()


    await example.handleStatusChangeRequest(stub)

    expect(example.handleErrorDisplay).toHaveBeenCalled()
    expect(example.handleErrorDisplay).toHaveBeenCalledWith(fakeError)
  });
});

有根据的免责声明:被测单元的模拟方法是一种气味。考虑检查调用handleStatusChangeSuccesshandleErrorDisplay的预期效果,而不要检查是否已调用它们。然后,除非该类的使用者需要访问,否则不要公开公开这些方法。

答案 2 :(得分:0)

  

有意见的免责声明:被测单元的模拟方法是一种   闻。考虑检查通话的预期效果   handleStatusChangeSuccesshandleErrorDisplay而不是检查   看看他们是否被召集。然后甚至不公开那些方法   除非该类的消费者需要访问,否则应公开。

完全同意反对webprojohn的免责声明。嘲笑是一种气味,因为测试应该断言代码的行为,而不是其实现。对后者进行测试会使代码难以更改。

离开我的肥皂盒... :)我们正在寻找一种测试异步方法的方法。我不确定您的测试应该做出什么断言来验证handleStatusChangeSuccess()handleErrorDisplay(err)内部的行为,因此下面的示例在这些断言的去处留下了注释。以下使用Promise.resolve()Promise.reject()触发测试结果。我用过async / await,Jest有other async examples in their docs

const Example = require('./example')

describe('handleStatusChangeRequest', () => {
  it('should resolve successfully', async () => {
    const {handleStatusChangeRequest} = new Example();
    const resolvePromise = () => Promise.resolve();

    await handleStatusChangeRequest(resolvePromise);

    // resolution assertions here
  });

  it('should resolve errors', async () => {
    const {handleStatusChangeRequest} = new Example();
    const fakeError = new Error('eep');
    const rejectPromise = () => Promise.reject(fakeError);

    // if your method doesn't throw, we can remove this try/catch
    // block and the fail() polyfill
    try {
      await example.handleStatusChangeRequest(rejectPromise);

      // if we don't throw our test shouldn't get here, so we
      // polyfill a fail() method since Jest doesn't give us one.
      // See https://github.com/facebook/jest/issues/2129
      expect(true).toBe(false);
    }
    catch (e) {
      // rejection assertions here
    }
  });
});

答案 3 :(得分:0)

我的答案看起来像这样:

**Success tests
const instance = el.find(EntryToolBar).instance()
const spy = jest.spyOn(instance, 'handleStatusChangeSuccess')

await instance.handleStatusChangeRequest(() => Promise.resolve('cool man'))

expect(spy).toHaveBeenCalledTimes(1)

**Error tests
const instance = el.find(EntryToolBar).instance()
const spy = jest.spyOn(instance, 'handleErrorDisplay')

await instance.handleStatusChangeRequest(() => Promise.reject(Error('shit')))
expect(spy).toHaveBeenCalledTimes(1)

如上所述,handleStatusChangeSuccesshandleError方法是在其他快照下进行测试的(它们只是设置状态并渲染一些不同的jsx)。我对此感觉很好。我正在使用间谍/模拟,但我正在其他地方测试实现功能。足够?