Testing 如何在测试不失败的情况下获得Jest toThrow的覆盖率

Testing 如何在测试不失败的情况下获得Jest toThrow的覆盖率,testing,jestjs,code-coverage,enzyme,throw,Testing,Jestjs,Code Coverage,Enzyme,Throw,假设我正在使用jest-coverage测试以下React组件: 覆盖率报告将显示新错误“无效”的行被发现。因为.not.toThrow似乎没有涵盖任何内容,我用酶创建了以下测试: const wrapper = shallow( <MyComponent invalid /> ) it('should throw', () => { function fn() { if (wrapper.instance().props.invalid) { t

假设我正在使用jest-coverage测试以下React组件:

覆盖率报告将显示新错误“无效”的行被发现。因为.not.toThrow似乎没有涵盖任何内容,我用酶创建了以下测试:

const wrapper = shallow(
  <MyComponent invalid />
)

it('should throw', () => {
  function fn() {
    if (wrapper.instance().props.invalid) {
      throw new Error('invalid')
    }
  }
  expect(fn).toThrow()
})
线被遮住了!然而,测试本身失败了,遇到了声明异常——这意味着原始组件应该抛出错误吗


我用错了吗?

galki,我认为问题是在构造组件时抛出了错误。而且它没有通过测试,这应该是正确的。 相反,如果您可以在其他地方提取道具检查功能,在安装过程中不会调用该功能,那么它将非常有效。例如,我将您的代码片段修改为

export default class MyComponent extends React.Component {
  constructor(props) {
    super(props)
  }
  componentWillReceiveProps(nextProps) {
    if (nextProps.invalid) {
      throw new Error('invalid')
    }
  }
  render() {
    return (
      <div/>
    )
  }
}


所以,如果您有机会在安装时不抛出错误,您将能够测试它。

galki,我认为问题在于您在构建组件时抛出错误。而且它没有通过测试,这应该是正确的。 相反,如果您可以在其他地方提取道具检查功能,在安装过程中不会调用该功能,那么它将非常有效。例如,我将您的代码片段修改为

export default class MyComponent extends React.Component {
  constructor(props) {
    super(props)
  }
  componentWillReceiveProps(nextProps) {
    if (nextProps.invalid) {
      throw new Error('invalid')
    }
  }
  render() {
    return (
      <div/>
    )
  }
}


因此,如果您有机会在装载时不抛出错误,您将能够对其进行测试。

显然,这是连接到的。我通过使用具有componentDidCatch方法的父React组件包装MyComponent,成功地通过了测试

这使得测试通过了,但为了影响覆盖率,我不得不将“浅”改为“装载”。测试结果如下所示:

class ParentComponent extends React.Component {
  componentDidCatch(error) {
    // console.log(error)
  }
  render() {
    return this.props.children
  }
}

class MyComponent extends React.Component {
  constructor(props) {
    super(props)
    if (props.invalid) {
      throw new Error('invalid')
    }
  }
}

const wrapper = mount(
  <ParentComponent>
    <MyComponent invalid />
  </ParentComponent>
)

it('should throw', () => {
  function fn() {
    if (wrapper.props().invalid) {
      throw new Error('invalid test')
    }
  }
  expect(fn).toThrow()
})

显然,这与我们的工作有关。我通过使用具有componentDidCatch方法的父React组件包装MyComponent,成功地通过了测试

这使得测试通过了,但为了影响覆盖率,我不得不将“浅”改为“装载”。测试结果如下所示:

class ParentComponent extends React.Component {
  componentDidCatch(error) {
    // console.log(error)
  }
  render() {
    return this.props.children
  }
}

class MyComponent extends React.Component {
  constructor(props) {
    super(props)
    if (props.invalid) {
      throw new Error('invalid')
    }
  }
}

const wrapper = mount(
  <ParentComponent>
    <MyComponent invalid />
  </ParentComponent>
)

it('should throw', () => {
  function fn() {
    if (wrapper.props().invalid) {
      throw new Error('invalid test')
    }
  }
  expect(fn).toThrow()
})

意识到这是一个古老的问题,但对于未来的观众,我想我应该扩展@galki的答案。您不必使用try/catch,只需将shallow/mount包装在匿名函数中,然后使用.tothrower即可:


这给了你更清晰的代码,同样的结果。

意识到这是一个老问题,但对于未来的观众,我想我会扩展@galki的答案。您不必使用try/catch,只需将shallow/mount包装在匿名函数中,然后使用.tothrower即可:


这会使代码更简洁,结果也一样。

这不是应该的吗fn。toThrow@AndreasKöberle这不应该是期待fn吗。toThrow@AndreasKöberle componentWillReceiveProps在本例中不被调用。我想测试组件的创建,而不是updatecomponentWillReceiveProps,在这种情况下不调用。我想在组件创建上进行测试,而不是在更新上进行测试。您保存了哪些内容,这是正确的。TothRow仅适用于纯函数,如果我们使用渲染器或浅层,则此测试不起作用。与其使用let并分配try/catch的结果,为什么不将浅层封装在匿名函数中并对其调用.TothRower?例如,expect=>shall.tothrowerr;哇,你救了我,没错。TothRow仅适用于纯函数,如果我们使用渲染器或浅层,则此测试不起作用。与其使用let并分配try/catch的结果,为什么不将浅层封装在匿名函数中并对其调用.TothRower?例如,expect=>shall.tothrowerr;这也适用于无状态:expect=>shallowTestComponent.tothroweror;这也适用于无状态:expect=>shallowTestComponent.tothroweror;
class MyComponent extends React.Component {
  constructor(props) {
    super(props)
    if (props.invalid) {
      throw new Error('invalid')
    }
  }
}

it('should throw', () => {
  let error
  try {
    shallow(<MyComponent invalid />)
  } catch (e) {
    error = e
  }
  expect(error).toBeInstanceOf(Error)
})
const TestComponent = () => {
    throw new Error('Test error');
}

describe('Test Component', () => {
    it('Throws an error', () => {
        expect(() => shallow(<TestComponent />)).toThrowError();
    });
});