【问题标题】:How to test function calling multiple other functions?如何测试调用多个其他函数的函数?
【发布时间】:2019-06-27 13:22:43
【问题描述】:

我正在编写一个 ExpressJS 中间件,它稍微修改请求对象并检查用户是否有权访问该特定页面。我对它进行单元测试有问题。我已经为每个方法编写了单独的测试,除了一个:handler。如何测试handler 功能?我应该测试它吗?或者我应该用istanbul ignore next 忽略它,因为我已经涵盖了所有其他功能?或者也许我应该以某种方式重写我的handler 函数以使其可测试?

class Example {

constructor(request, response, next, userAccountService) {
    this.req = request;
    this.res = response;
    this.next = next;
    this.userAccountService = userAccountService;
}

removeTokenFromQuery() {
    delete this.req.query.token;
}

isValidRequest() {
    if (!this.req.secure) {
        return false;
    }

    if (typeof this.req.query.token !== 'undefined') {
        return false;
    }

    if (typeof this.req.query.unsupportedQueryParam !== 'undefined') {
        return false;
    }

    return true;
}

isPageAccessibleForUser() {
    return this.userAccountService.hasAccess('example');
}

async handler() {
    this.removeTokenFromQuery();

    if (!this.isValidRequest()) {
        throw new Error('Invalid request');
    }

    if (!this.isPageAccessibleForUser()) {
        this.res.statusCode(500);
        this.res.end();
        return;
    }

    this.next();
}

}

然后它被称为 Express 中间件:

this.app.use((res, req, next) => {
    const exampleObj = new Example(res, req, next, userAccServ);
    exampleObj.handler();
});

【问题讨论】:

    标签: javascript unit-testing express mocha.js


    【解决方案1】:

    我应该测试一下吗?

    是的,根据您的示例处理程序包含(看起来是)一些关键业务逻辑。它负责编排

    • 从请求中删除令牌(安全)
    • 确定请求是否有效(安全/身份验证)
    • 确定用户是否可以访问页面(安全/身份验证)

    如果这个功能没有经过测试,未来的工程师可能会对这个重要的功能进行修改,而他们不会收到任何关于他们的修改的反馈。假设由于人为错误,他们不小心删除了 isValidRequest 检查?或删除!。然而,与测试它所需的相对较少的工作量相比,与这种情况相关的风险不太可能是灾难性的。

    如何测试处理函数?

    下一个问题是你如何实际测试这个 :) 我会选择在可能的最低“级别”lower 进行测试(单元通过直接调用此方法与 higher(通过 express 框架)。

    正如您所提到的,handler 委托给的每个功能的实现都有测试,IMO 在handler 中测试的重要事情是流程而不是实现(因为这些已经经过充分测试)。

    describe('handler()', () => {
      it('removes token from query');
      it('errors on invalid request');
      it('returns 500 status code when page is inaccessible');
      it('continues with .next() when request is valid and page is accessible');
    })
    

    为此,我将实例化Example,然后修补必要的方法,以便为您的handler() 测试创建正确的流程。所以对于无效请求测试,这可能看起来像:

    const example = new Example();
    sinon.stub(example, "isValidRequest").returns(false);
    

    如果这没有被存根,那么这些测试基本上会复制其他测试(通过测试实际实现)。使用存根可以更改 isValidRequest 的实现,同时在 handler 中仍具有单元测试保护

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-18
      • 1970-01-01
      • 1970-01-01
      • 2022-07-31
      • 1970-01-01
      相关资源
      最近更新 更多