首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Sinon使用酶浅层渲染进行短桩

使用Sinon使用酶浅层渲染进行短桩
EN

Stack Overflow用户
提问于 2017-03-08 08:03:10
回答 1查看 727关注 0票数 0

我有一个从JS组件移植过来的React组件。我正在迁移并检查测试,我得到了许多失败,因为存根似乎不再工作。这是我的组件。

代码语言:javascript
复制
import DeleteButton from "./delete-button.jsx"
import Dialogs from "../../dialogs";
import React from "react";
import UrlHelper from "../../helpers/url-helper";

export default class ActiveDeleteButton extends React.Component {

    /**
     * Creates an instance of ActiveDeleteButton.
     * 
     * @param {object} props The react props collection.
     * 
     * @memberOf ActiveDeleteButton
     */
    constructor(props) {
        super (props);

        this.handleConfirmDelete = this.handleConfirmDelete.bind(this);
    }

    handleConfirmDelete() {
        $.ajax({
            url: this.props.deleteUri,
            type: `DELETE`,
            contentType: `application/json; charset=utf-8`,
            cache: false,
            success: (xhr) => {
                let successUri = this.props.successUri;
                if (!successUri && xhr && xhr.uri) { successUri = xhr.uri; }
                if (successUri) { UrlHelper.redirect(successUri); }
            },
            error: (xhr, status) => {
                this.showFailed();
            }
        });
    }

    /**
     * Shows failure of deletion.
     * 
     * @memberOf ActiveDeleteButton
     */
    showFailed() {
        Dialogs.alert(this.props.errorMessage);
    }

    /**
     * Renders the component to the DOM.
     * 
     * @returns the HTML to render.
     * 
     * @memberOf ActiveDeleteButton
     */
    render() {
        return (
            <DeleteButton text = {this.props.text}
                          title = {this.props.title}
                          cancelText = {this.props.cancelText}
                          confirmText = {this.props.confirmText}
                          message = {this.props.message}
                          onConfirmDelete = {this.handleConfirmDelete} />
        );
    }
}

下面是测试(精简)..。

代码语言:javascript
复制
describe("performs a DELETE AJAX request", () => {

    it ("for specified URLs", sinon.test(function() {
        let wrapper = shallow(<ActiveDeleteButton text = "Click Me"  />);
        let instance = wrapper.instance(); 
        let ajaxStub = this.stub($, 'ajax');
        instance.forceUpdate()
        wrapper.update()
        instance.handleConfirmDelete();
        console.log(ajaxStub.getCall(0));
        let options = ajaxStub.getCall(0).args[0];
        assert.equal(options.url, objUt.deleteUri);
        assert.equal(options.type, "DELETE");
    }));
}));

我遇到的问题是'ajaxStub.getCall(0)‘返回null。这应该会返回Ajax调用,这样我就可以检查args (以前在我的旧JS组件中也是如此)。存根永远不会被调用,尽管(在我看来)它显然应该被调用。

我是不是漏掉了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-08 21:47:56

这更多的是一种变通方法,所以一个更好的答案将是很好的。最后,我为此构建了一个解决方案,如下所示:

首先,我创建了一个新类来处理Ajax请求。

代码语言:javascript
复制
/**
 * An AJAX request wrapper.
 * Usage of this enables testing AJAX calls.
 * 
 * @export AjaxRequest
 * @class AjaxRequest
 * @extends {AjaxRequest}
 */
export default class AjaxRequest {

    /**
     * Creates an instance of AjaxRequest.
     * @param {any} { url, type, contentType, cache, data, successCallback, errorCallback } 
     * 
     * @memberOf AjaxRequest
     */
    constructor({ url, type, contentType, cache, data, successCallback, errorCallback }) {
        Guard.throwIf(url, "url");
        let emptyFunc = () => {};

        this.url = url;
        this.type = type.toUpperCase() || "GET";
        this.contentType = contentType || "application/json; charset=utf-8";
        this.dataType = "json";
        this.cache = cache || false;
        this.data = data ? JSON.stringify(data) : undefined;
        this.successCallback = successCallback || emptyFunc;
        this.errorCallback = errorCallback || emptyFunc;
    }

    /**
     * Executes the AJAX request.
     * 
     * 
     * @memberOf AjaxRequest
     */
    execute() {
        $.ajax({
            url: this.url,
            type: this.type,
            contentType: this.contentType,
            dataType: this.dataType,
            cache: this.cache,
            data: this.data,
            success: this.successCallback,
            error: this.errorCallback
        });
    }

    /**
     * Gets a GET request.
     * 
     * @static
     * @param {string} url 
     * @param {function} successCallback 
     * @param {function} errorCallback 
     * @returns an AjaxRequest
     * 
     * @memberOf AjaxRequest
     */
    static get(url, successCallback, errorCallback) {
        return new AjaxRequest({
            url: url,
            type: 'GET',
            successCallback: successCallback,
            errorCallback: errorCallback
        });
    }

    /**
     * Gets a POST request.
     * 
     * @static
     * @param {string} url 
     * @param {object} data
     * @param {function} successCallback 
     * @param {function} errorCallback 
     * @returns an AjaxRequest
     * 
     * @memberOf AjaxRequest
     */
    static post(url, data, successCallback, errorCallback) {
        return new AjaxRequest({
            url: url,
            data: data,
            type: 'POST',
            successCallback: successCallback,
            errorCallback: errorCallback
        });
    }

    /**
     * Gets a PUT request.
     * 
     * @static
     * @param {string} url 
     * @param {object} data
     * @param {function} successCallback 
     * @param {function} errorCallback 
     * @returns an AjaxRequest
     * 
     * @memberOf AjaxRequest
     */
    static put(url, data, successCallback, errorCallback) {
        return new AjaxRequest({
            url: url,
            data: data,
            type: 'PUT',
            successCallback: successCallback,
            errorCallback: errorCallback
        });
    }

    /**
     * Gets a DELETE request.
     * 
     * @static
     * @param {string} url
     * @param {function} successCallback 
     * @param {function} errorCallback 
     * @returns an AjaxRequest
     * 
     * @memberOf AjaxRequest
     */
    static delete(url, successCallback, errorCallback) {
        return new AjaxRequest({
            url: url,
            type: 'DELETE',
            successCallback: successCallback,
            errorCallback: errorCallback
        });
    }
}

(我觉得这里有一定数量的轮子重新发明)。然后我在组件中更新了我的方法调用,如下所示...

代码语言:javascript
复制
handleConfirmDelete() {
    AjaxRequest.delete(this.props.deleteUri,
        (xhr) => {
            let successUri = this.props.successUri;
            if (!successUri && xhr && xhr.uri) { successUri = xhr.uri; }
            if (successUri) { UrlHelper.redirect(successUri); }
        },
        (xhr, status) => {
            this.showFailed();
        }
    ).execute();
}

我现在可以像下面这样测试...

代码语言:javascript
复制
describe("performs a DELETE AJAX request", () => {
    let wrapper = null;
    let instance = null;
    let ajaxStub = null;
    let urlHelperRedirectStub = null;

    beforeEach(() => {
        ajaxStub = sinon.stub(AjaxRequest.prototype, 'execute');
        urlHelperRedirectStub = sinon.stub(UrlHelper, 'redirect');
        wrapper = shallow(<ActiveDeleteButton text = "Click Me"  />);
        instance = wrapper.instance(); 
    });

    afterEach(() => {
        ajaxStub.restore();
        urlHelperRedirectStub.restore();
    });

    it ("for default URLs", sinon.test(function() {
        instance.handleConfirmDelete();
        sinon.assert.called(ajaxStub);
        let requestInfo = ajaxStub.getCall(0).thisValue;          

        assert.equal(UrlHelper.current.url().split('?')[0], requestInfo.url);
    }));

    it ("for specified URLs", sinon.test(function() {
        wrapper = shallow(<ActiveDeleteButton text = "Click Me" deleteUri="http://localhost/items/12" />);
        instance = wrapper.instance();

        instance.handleConfirmDelete();
        sinon.assert.called(ajaxStub);
        let requestInfo = ajaxStub.getCall(0).thisValue;          

        assert.equal("http://localhost/items/12", requestInfo.url);
    }));
}));

使用存根调用的thisValue属性,我可以获取回调并手动执行它们,以根据不同的输入对它们进行测试。考虑到所需的努力,这不是一个理想的解决方案,但它是有效的,并且是可重用的。

然而,我觉得肯定有更好的方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42660626

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档