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

Mocha ignores some tests although they should be run

我正在正确地重构我的 express-decorator NPM package. This includes refactoring the unit tests that were previously done using AVA. I decided to rewrite them using Mocha and Chai 克隆,因为我更喜欢他们定义测试的方式。

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

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()
      })
  })
})

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

那么如何让测试生效呢?我的想法是以某种方式 将上下文 (测试套件)传递给 it 函数,但这对 Mocha 来说是不可能的,是吗?

看起来您正在从 tape 或一些类似的测试运行器转移到 Mocha。您将需要显着改变您的方法,因为 Mocha 的工作方式有很大不同。

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

所以您的 Mocha 代码不起作用的原因是因为您正在创建测试 Mocha 开始运行 测试后。 Mocha 不会立即让你崩溃,但是当你这样做时,你得到的行为是不确定的。我见过 Mocha 忽略新测试的情况,也见过它以意外顺序执行的情况。

如果这是我的测试,我会做的是:

  1. foo 中删除对 it 的调用。

  2. foo修改为在controller实例上简单记录我关心的请求参数

    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 挂钩在测试之间重置控制器,以便隔离测试。