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

gal*_*lki 1 testing code-coverage throw jestjs enzyme

假设我正在测试下面的React组件jest --coverage:

class MyComponent extends React.Component {
  constructor(props) {
    super(props)
    if (props.invalid) {
      throw new Error('invalid')
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

覆盖率报告将说明该线路throw new Error('invalid')未被发现.既然.not.toThrow()似乎没有涵盖任何东西,我用酶制作以下测试:

const wrapper = shallow(
  <MyComponent invalid />
)

it('should throw', () => {
  function fn() {
    if (wrapper.instance().props.invalid) {
      throw new Error('invalid')
    }
  }
  expect(fn).toThrow()
})
Run Code Online (Sandbox Code Playgroud)

这条线被覆盖了!然而,测试本身失败了encountered a declaration exception- 意味着原始组件抛出了错误(应该如此)?

我用toThrow()错了吗?

tom*_*der 6

意识到这是一个老问题,但对于未来的观众,我想我会扩展@galki 的答案。您可以简单地将shallow/包装mount在一个匿名函数中,然后使用.toThrowError()

const TestComponent = () => {
    throw new Error('Test error');
}

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

这为您提供了更清晰的代码,并具有相同的结果。


gal*_*lki 5

显然这与React 16处理错误的方式有关.我设法通过MyComponent包含具有componentDidCatch方法的父React组件来传递测试.

这使测试通过但影响覆盖范围,我不得不shallow改为mount.测试最终看起来像这样:

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()
})
Run Code Online (Sandbox Code Playgroud)

UPDATE

在意识到问题是被抛入内部shallow或者mount(在它进入测试之前)之后,我将整个事情简化为:

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)
})
Run Code Online (Sandbox Code Playgroud)