我如何用jest测试这个基于承诺的代码?

vltsax25  于 2023-02-27  发布在  Jest
关注(0)|答案(4)|浏览(203)

我该如何用笑话测试这段代码呢?我想确保传递的promise的错误和成功在需要的时候被调用。我相信这是一件简单的事情,但是它让我发疯了。非常感谢。

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

bnl4lu3b1#

如果你的代码使用promise,有一个很好的方法来处理异步测试,从你的测试返回一个promiseJest将等待promise解析。

如果承诺被拒绝,测试将自动失败。

例如,假设changeData不使用回调,而是返回一个promise,该promise应该解析为字符串 “status has been successful modified”
请确保**return**promise-如果省略此return语句,则测试将在changeData()-[async function]完成之前完成。

以下是一个方便且易于遵循的模式

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

快乐测试:)

jucafojl

jucafojl2#

这是可以重构的,但是为了演示起见,我保留了重复的部分。
example.spec.js中,回调changeEntryStatus被存根化以返回一个promise。为了检查是否调用了其他示例方法(this.method),首先模拟它们,然后在运行被测试的方法之后在模拟上调用Assert。在Jest docs中了解更多。(请参阅底部关于模拟被测试单元的方法的想法。)
Run the example on repl.it.

示例.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;

示例规范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的预期效果,而不是检查它们是否被调用。然后甚至不要公开这些方法,除非类的消费者需要访问。

ctzwtxfj

ctzwtxfj3#

**个人意见免责声明:**模拟被测单元的方法是一种气味。考虑检查调用handleStatusChangeSuccesshandleErrorDisplay的预期效果,而不是检查它们是否被调用。然后甚至不要公开这些方法,除非类的消费者需要访问。

我完全同意webprojohn的免责声明。模拟测试是一种气味,因为测试应该Assert代码的行为,而不是它的实现。测试后者会使代码变得脆弱。
站在我的讲台上...:)我们正在寻找一种测试异步方法的方法。我不确定您的测试应该使用什么Assert来验证handleStatusChangeSuccess()handleErrorDisplay(err)内部的行为,所以下面的示例在这些Assert的位置留下了注解。下面的示例使用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
    }
  });
});
tgabmvqs

tgabmvqs4#

我的答案是这样的:

成功测试

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

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

expect(spy).toHaveBeenCalledTimes(1)

错误测试

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)。我对此感觉很好。我使用spys/mock,但我在其他地方测试实现函数。足够了吗?

相关问题