React不提供允许您将上下文传递给已创建的组件类的API,因此您必须编写一个提供上下文的包装器组件。
不幸的是,一旦你这样做,你就不再可以直接访问你想要测试的组件 - 与TestUtils.renderIntoDocument
不同,像TestUtils.findRenderedComponentWithType
这样的函数不返回实际的渲染组件实例,它们只返回组件构造函数。因此,您无法在执行测试之前调用组件上的方法,或将组件状态设置为某个已知值。您唯一可以访问的是组件的DOM节点,如果你想做的只是黑盒测试,但是对于某些类型的组件是不够的,这很好。
我很想知道是否有人为此提出了解决方案。我尝试过十几种不同的方法,但都没有。 (例如,我尝试在我的包装器组件中使用'ref',但它有同样的问题 - 不能让你访问真实对象。)
答案 0 :(得分:3)
(回答我自己的问题)
对所有这一切的正确答案是使用enzyme,它取代了标准的React测试工具 - 它提供了大量的功能与类似jQuery的API,最重要的是它完全支持组件上下文。我已将所有测试都转换为它,这很棒!
答案 1 :(得分:0)
您可以构建一个模拟父组件,如:
class MockContextContainer extends Component {
static propTypes = {
children: PropTypes.element.isRequired,
};
static childContextTypes = {
onSetTitle: PropTypes.func,
};
getChildContext() {
return {
onSetTitle: () => {},
};
}
render() {
return this.props.children;
}
}
然后在测试中使用它(在这种情况下,它是一个忘记密码的形式示例):
const cxtForgot = TestUtils.renderIntoDocument(
<MockContextContainer><ForgotPasswordForm /></MockContextContainer>
);
您可能已经在做什么。 然后你可以做以下事情:
const input = TestUtils.findRenderedDOMComponentWithClass(
cxtForgot, 'ForgotPasswordForm-input'
);
// enter a valid email
input.value = 'abc@hotmail.com';
TestUtils.Simulate.change(input);
// no error class and button is now enabled
assert(!input.classList.contains('error'));
const button1 = TestUtils.findRenderedDOMComponentWithClass(
cxtForgot, 'primary-button'
);
assert(!button1.disabled);
上面的Simulate.change可以改变组件的内部状态。 至于你的问题:“在执行测试之前将组件状态设置为某个已知值”,你可以将不同的道具传递给组件,并为每个场景进行不同的测试