【问题标题】:MochaJS: How to share assertion/"it('should')" code between testsMochaJS:如何在测试之间共享断言/“it('should')”代码
【发布时间】:2016-01-10 06:24:09
【问题描述】:

我使用 Nodejs 运行了一些 mocha 测试来测试 Web 服务器。

许多测试会导致服务器返回错误,例如400 错误请求。

目前测试中充斥着以下代码的许多副本:

it('should respond with 400 (Bad Request)', function (){
    expect(httpResponse.statusCode).to.equal(httpstatus.BAD_REQUEST);
});

这是一个简化的伪代码示例:

describe('When passing bad JSON data', function(){
    var response
    before(function(done){
        callUrlToInsert(url, badJson, function(err, resp){
            response = resp
            done()
        }
    }
    it('should respond with 400 (Bad Request)', function (){
        expect(httpResponse.statusCode).to.equal(httpstatus.BAD_REQUEST)
    })
}

这让我很烦恼,因为作为一名程序员,我尽可能避免重复代码。

但是,将其放入函数中是行不通的:

function verifyItReturnedBadRequest400(httpResponse)
{
    it('should respond with 400 (Bad Request)', function (){
        expect(httpResponse.statusCode).to.equal(httpstatus.BAD_REQUEST);
    });
}

因为对it() 的调用不会立即测试断言;我的 [有限] 理解是 it() 将闭包添加到测试列表中。因此,当检查完成时,httpResponse 变量已超出范围。 (我不明白为什么会这样,因为在这两种情况下都会调用它();为什么在一种情况下它在另一个级别的函数调用中很重要?我可能遗漏了一些关于Javascript 范围。)

是否有避免所有这些重复代码的通用方法?还是每个人都在到处复制他们所有的断言代码?这是我第一次尝试 Mocha,所以我可能遗漏了一些明显的东西。

另外,解释为什么函数方法不起作用?

谢谢!

【问题讨论】:

  • 摩卡中有一种叫做钩子的东西。哪个将块之前,之后,之前和之后。但我不确定这些钩子是否能够运行测试。
  • 我的印象是 hooks 是用来 setup 和 teardown 的,但是检查结果必须在实际测试中完成。但我可能是错的。将它('应该')放在“之后”钩子中是否有意义?
  • 是的,你是对的。钩子主要用于设置,但到目前为止,只有当钩子支持运行测试时,我才看到任何其他选项。我建议试一试。

标签: node.js unit-testing mocha.js


【解决方案1】:

wiki 上有一篇关于此的文章。 https://github.com/mochajs/mocha/wiki/Shared-Behaviours

我猜你的测试中有一些错误。将 it() 放入包装函数中可以正常工作。这是一个小型的工作演示。

'use strict';

const assert = require('assert');

const xEqualsOne = () => {
  it('should be equal 1', () => {
    assert.equal(this.x, 1);
  });
};

describe('async number', () => {
  this.x = 0;

  before(done => {
    this.x++
    setTimeout(done, 100);
  });

  xEqualsOne();
});

【讨论】:

  • 您的测试有效,因为您没有将任何参数传递给 xEqualsOne,因此它正在测试一个全局变量。我宁愿不使用这样的全局变量。但它在正确的轨道上;请参阅@N3dst4 的答案以获得更深入的解释。它与您的类似,但在 describe 上下文中声明了测试数据。
  • 实际上,您的代码符合 Mocha wiki 的建议:将数据存储在 this 上下文中。所以,+1。
【解决方案2】:

我猜你的代码看起来像这样:

describe('When passing bad JSON data', function(){
    var response
    before(function(done){
        callUrlToInsert(url, badJson, function(err, resp){
            response = resp
            done()
        }
    }
    verifyItReturnedBadRequest400(httpResponse)
}

这样想:

  1. it() 创建一个测试。
  2. it 的所有调用都发生在任何测试实际运行之前(您必须在运行它们之前创建测试)
  3. 传递给 `before' 的函数在测试创建后运行,但 before 它们运行。
  4. verifyItReturnedBadRequest400 调用 it, 来创建一个测试,但是您在任何测试运行之前就传递了 httpResponse,所以 before 还没有运行。

您可以继续使用这种模式,但您需要将 httpresponse 放入容器中,以便传递对它的引用:

describe('When passing bad JSON data', function(){
    var data = {};
    before(function(done){
        callUrlToInsert(url, badJson, function(err, resp){
            data.response = resp
            done()
        }
    }
    verifyItReturnedBadRequest400(data)
}

然后你的verifyItReturnedBadRequest400 变成:

function verifyItReturnedBadRequest400(data) {
    it('should respond with 400 (Bad Request)', function (){
        expect(data.response.statusCode).to.equal(httpstatus.BAD_REQUEST);
    });
}

【讨论】:

  • 感谢您的详细解释和链接!您不仅解释了正在发生的事情,还提供了一个可行的解决方案和一个描述此场景的行业标准的链接。因此在调用it() 之后设置response 不会影响传递给it 的变量,但是传递对容器的引用允许我更新容器以在调用it() 后保存响应。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-13
  • 2021-05-15
  • 2016-10-19
  • 2021-06-23
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
相关资源
最近更新 更多