Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 用酶don和x27进行单元试验;t重新绑定辅助函数的上下文_Javascript_Reactjs_Enzyme - Fatal编程技术网

Javascript 用酶don和x27进行单元试验;t重新绑定辅助函数的上下文

Javascript 用酶don和x27进行单元试验;t重新绑定辅助函数的上下文,javascript,reactjs,enzyme,Javascript,Reactjs,Enzyme,这是我在尝试使用AirBnB的React测试库重构一些React组件时遇到的一个有趣问题 我认为最好的解释我的问题的方法是通过一个例子 下面是一个小的React组件,它将根据从其父组件接收到的道具显示一条消息: test.js: import React from 'react'; function renderInnerSpan() { const {foo} = this.props; if (foo) { return <span>Foo i

这是我在尝试使用AirBnB的React测试库重构一些React组件时遇到的一个有趣问题

我认为最好的解释我的问题的方法是通过一个例子

下面是一个小的React组件,它将根据从其父组件接收到的道具显示一条消息:

test.js:

import React from 'react';

function renderInnerSpan() {
    const {foo} = this.props;

    if (foo) {
        return <span>Foo is truthy!</span>;
    }

    return <span>Foo is falsy!</span>;
}

export default class extends React.Component {
    render() {
        return (
            <div>
                {renderInnerSpan.call(this)}
            </div>
        );
    }    
}
import Test from '../../src/test';

import React from 'react';
import {shallow} from 'enzyme';
import {expect} from 'chai';

describe('Test Suite', () => {
    let renderedElement,
        expectedProps;

    function renderComponent() {
        const componentElement = React.createElement(Test, expectedProps);

        renderedElement = shallow(componentElement);
    }

    beforeEach(() => {
        expectedProps = {
            foo: true
        };

        renderComponent();
    });

    it('should display the correct message for truthy values', () => {
        const span = renderedElement.props().children;

        expect(span.props.children).to.equal('Foo is truthy!');
    });

    it('should display the correct message for falsy values', () => {
        expectedProps.foo = false;
        renderComponent();

        const span = renderedElement.props().children;

        expect(span.props.children).to.equal('Foo is falsy!');
    });
});
这很好,但是测试组件的当前实现并没有它可能的那么高效。通过使用
.call(this)
,每次调用
render()
函数时,它都会创建一个新函数。我可以通过在组件的构造函数中绑定
this
的正确上下文来避免这种情况,如下所示:

export default class extends React.Component {
    constructor(props) {
        super(props);

        renderInnerSpan = renderInnerSpan.bind(this);
    }

    render() {
        return (
            <div>
                {renderInnerSpan()}
            </div>
        );
    }
}
我在构造函数中添加了一个
console.log(props.foo)
,它确认了构造函数在我期望的时候仍然被调用,并且它接收的道具是正确的。但是,我在
renderinerspan
中添加了
console.log(foo)
,看起来该值一直都是真的,即使在重新渲染组件后,其
foo
属性显式设置为
false

看起来
renderinerspan
只能绑定一次,而酵素在每次测试中都会重复使用它。那么,有什么好处呢?我正在测试中重新创建我的组件,它用我期望的值调用它的构造函数-为什么我的绑定
renderinerspan
函数继续使用旧值


提前感谢您的帮助。

我认为您在类之外定义了renderInnerSpan函数,这可能会产生一些问题

试试这个:

import React from 'react';


export default class extends React.Component {
  render() {
    return (
      <div>
        {this.renderInnerSpan.bind(this)}
      </div>
    );
  }

  renderInnerSpan() {
    const {foo} = this.props;

    if (foo) {
      return <span>Foo is truthy!</span>;
    }

    return <span>Foo is falsy!</span>;
  }
}
如果您在每次测试中都要更改道具,那么就没有理由在beforeach块中设置道具。只需在每个测试中使用新的renderComponent即可

it('should display the correct message for truthy values', () => {
    renderedElement = renderComponent({foo: true});
    const span = renderedElement.props().children;

    expect(span.props.children).to.equal('Foo is truthy!');
});

这里的问题是,一个函数不能被绑定多次,正如您在测试用例中试图绑定的那样

原因是上下文不仅仅是函数本身的属性。当一个函数被绑定时,它相当于被包装在一个容器中

上下文(
this
-assignment)保存在外来对象的
[[BoundThis]]
属性中。绑定函数将始终在此上下文中调用,即使它再次绑定


您可以自己进行测试:

函数foo(){
console.log(this.bar);
}
foo();//未定义
foo=foo.bind({bar:1});
foo();//1.
foo=foo.bind({bar:2});

foo();//1
没有理由不能在类的上下文之外定义
renderinerspan
。正如我在最初的帖子中所说,最初的实现是有效的。仅仅因为你可以,并不意味着你应该。renderInnerSpan属于类的上下文,应该在类内部定义。这将使函数可以公开访问,这是我非常反对的。它的当前位置使函数私有,这在测试组件行为时很重要。无状态功能组件似乎是一种解决方法。我最终采取了一种稍微不同的方法,将我的
renderinerspan
变成了一个SFC。谢谢你的解释,这现在更有意义了。
function renderComponent(expectedProps) {
    const componentElement = React.createElement(Test, expectedProps);

    return shallow(componentElement);
}
it('should display the correct message for truthy values', () => {
    renderedElement = renderComponent({foo: true});
    const span = renderedElement.props().children;

    expect(span.props.children).to.equal('Foo is truthy!');
});