摩卡忽略了一些测试,尽管它们应该运行

时间:2017-08-31 17:48:10

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

我正在努力重构我的express-decorator NPM包的克隆。这包括重构先前使用the unit tests完成的AVA。我决定使用MochaChai重写它们,因为我更喜欢它们定义测试的方式。

那么,我的问题是什么?看看这段代码(我将其分解来说明问题):

test('express', (t) => {
  @web.basePath('/test')
  class Test {

    @web.get('/foo/:id')
    foo(request, response) {
      /* The test in question. */
      t.is(parseInt(request.params.id), 5);
      response.send();
    }

  }

  let app = express();
  let controller = new Test();
  web.register(app, controller);
  t.plan(1);

  return supertest(app)
    .get('/test/foo/5')
    .expect(200);
});

此代码有效

这是(基本上)相同的代码,现在使用Mocha和Chai以及多次测试

describe('The test express server', () => {
  @web.basePath('/test')
  class Test {

    @web.get('/foo/:id')
    foo(request, response) {
      /* The test in question. */
      it('should pass TEST #1',
        () => expect(toInteger(request.params.id)).to.equal(5))
      response.send()
    }
  }

  const app = express()
  const controller = new Test()
  web.register(app, controller)

  it('should pass TEST #2', (done) => {
    return chai.request(app)
      .get('/test/foo/5')
      .end((err, res) => {
        expect(err).to.be.null
        expect(res).to.have.status(200)
        done()
      })
  })
})

问题是Mocha忽略了TEST #1,尽管在测试期间代码的部分运行。我试着console.log那里的东西,它出现在我希望它出现的Mocha日志中。

那么我该如何让这个测试起作用呢?我的想法是以某种方式将上下文(测试套件)传递给it函数,但这对Mocha来说是不可能的,或者是它?

1 个答案:

答案 0 :(得分:2)

看起来你正在从tape或类似的测试跑者转向Mocha。您需要显着改变您的方法,因为Mocha的工作方式有很大不同。

tape和类似的跑步者不需要提前知道套件中存在哪些测试。他们在执行测试代码时发现测试,测试可以包含另一个测试。另一方面,Mocha要求在运行任何测试之前可以发现整个套件。*它需要知道套件中将存在的每个测试。它有一些缺点,因为你不能在Mocha运行测试时添加测试。你不能拥有before钩子,例如从数据库和创建测试中进行查询。相反,您必须在套件启动之前执行查询。但是,这种做事方式也有一些优点。您可以使用--grep选项仅选择一部分测试,Mocha将毫无困难地执行此操作。您也可以使用it.only毫无困难地选择单个测试。最后我查了一下,tape和它的兄弟姐妹在这方面遇到了麻烦。

所以你的Mocha代码无效的原因是因为你在 Mocha开始运行测试后创建了一个测试 Mocha不会立即崩溃对你而言,当你这样做时,你得到的行为是不确定的。我已经看到Mocha会忽略新测试的情况,并且我已经看到了以意想不到的顺序执行它的情况。

如果这是我的测试,那我要做的是:

  1. it移除对foo的来电。

  2. 修改foo以简单记录我在控制器实例上关注的请求参数。

    foo(request, response) {
      // Remember to initialize this.requests in the constructor...
      this.requests.push(request);
      response.send()
    }
    
  3. 让测试it("should pass test #2"检查控制器上记录的请求:

    it('should pass TEST #2', (done) => {
      return chai.request(app)
        .get('/test/foo/5')
        .end((err, res) => {
          expect(err).to.be.null
          expect(res).to.have.status(200)
          expect(controler.requests).to.have.lengthOf(1);
          // etc...
          done()
        })
    })
    
  4. 并且会使用beforeEach挂钩在测试之间重置控制器,以便隔离测试。