【问题标题】:Why is this chai-as-promised AssertionError printing to the Console but not my Mocha test runner?为什么这个 chai-as-promised AssertionError 打印到控制台而不是我的 Mocha 测试运行器?
【发布时间】:2016-01-07 23:14:08
【问题描述】:

我很想测试一些使用带有chai-as-promised 和Mocha 的Promises 的代码。我的测试套件还利用fetch-mock 模拟通常使用 Fetch API 发送的 AJAX 请求。

这是我要测试的代码:

/**
 * Sends a POST request to save (either insert or update) the record
 * @param  {object} record simple object of column name to column value mappings
 * @return {Promise}       Resolves when the POST request full response has arrived.
 * Rejects if the POST request's response contains an Authorization error.
 */
save(record) {
  var _this = this;
  return this._auth(record)
    .then(function() {
      return window.fetch(_this._getPostUrl(), {
        method: 'post',
        headers: {
          'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
        },
        body: _this._objToPostStr(record),
        credentials: 'include'
      });
    })
    .then(function(saveResp) {
      return saveResp.text();
    })
    .then(function(saveResp) {
      return new Promise(function(resolve, reject) {
        if (saveResp.indexOf('Authorization') !== -1) {
          reject('Request failed');
        } else {
          resolve(saveResp);
        }
      });
    });
}

在我最上层的describe 中,我有一个最初设置我的fetchMock 对象的函数。

before(() => {
  fetchMock = new FetchMock({
    theGlobal: window,
    Response: window.Response,
    Headers: window.Headers,
    Blob: window.Blob,
    debug: console.log
  });
  fetchMock.registerRoute({
    name: 'auth',
    matcher: /tlist_child_auth.html/,
    response: {
      body: 'authResp',
      opts: {
        status: 200
      }
    }
  });
});

这是相关的测试代码:

describe('save', () => {
  it('save promise should reject if response contains the string Authorization', () => {

    fetchMock.mock({
      routes: ['auth', {
        name: 'save',
        matcher: /changesrecorded.white.html/,
        response: {
          body: 'Authorization',
          opts: {
            status: 200
          }
        }
      }]
    });

    let _getLocationStub = sinon.stub(client, '_getLocation');
    _getLocationStub.returns('/admin/home.html');

    client.foreignKey = 12345;
    let promise = client.save({
      foo: 'bar'
    });
    promise.should.eventually.be.fulfilled;
    fetchMock.unregisterRoute('save');
  });
});

我在fetchMock.mock() 调用中定义save 路由的原因是我有另一个测试需要重新定义save 路由以返回其他内容。

为了确保 chai-as-promised 确实有效并且会在测试失败时通知我,我编写了一个失败的测试 promise.should.eventually.be.fulfilled;。这将失败,因为如果响应包含 Authorization,save 返回的 Promise 将拒绝,它确实如此。 Chrome 控制台显示带有 message: expected promise to be fulfilled but it was rejected with 'Request failed 的 AssertionError,但我的 Mocha test-runner.html 页面显示此测试通过。由于某种原因,chai-as-promised 无法与 Mocha 正常通信。

如果您想查看我的整个项目,请查看 Github 上的 this repo。

任何想法为什么?

编辑:

这是我的测试设置代码:

let expect = chai.expect;
mocha.setup('bdd');
chai.should();
chai.use(chaiAsPromised);

【问题讨论】:

    标签: javascript unit-testing mocha.js chai-as-promised


    【解决方案1】:

    promise.should.eventually.be.fulfilled 的值是一个承诺,您应该返回它,以便 Mocha 知道您的测试何时结束。我创建了一个小测试文件来模拟您所看到的内容,我如果像您一样,我只是未能返回promise.should.eventually.be.fulfilled;,则可以完全复制该行为。这是一个有效的示例:

    import chai from "chai";
    import chaiAsPromised from "chai-as-promised";
    
    chai.use(chaiAsPromised);
    chai.should();
    
    describe("foo", () => {
        it("bar", () => {
            let promise = Promise.reject(new Error());
            return promise.should.eventually.be.fulfilled;
        });
    });
    

    在您的代码中,您在测试结束时有一些清理代码:fetchMock.unregisterRoute('save');。根据您显示的内容,我会将其移至 after 挂钩,以便它反映您的 before 挂钩。一般来说,after 应该执行与before 和afterEach 中的内容对应的清理beforeEach 中的内容。但是,如果您出于某种原因需要在测试中包含清理代码,您可以这样做:

            function cleanup() {
                console.log("cleanup");
            }
    
            return promise.should.eventually.be.fulfilled.then(
                // Called if there is no error, ie. if the promise was
                // fullfilled.
                cleanup,
                // Called if there is an error, ie. if the promise was
                // rejected.
                (err) => { cleanup(); if (err) throw err; });
    

    不幸的是,Chai 似乎返回了一些看起来像 ES6 Promise 但只是部分的东西。最终,它可能会返回一个实际的 ES6 承诺,然后无论发生什么情况,您都可以调用 .finally 运行清理代码并自动传播错误。

    【讨论】:

    • 看起来很明显,文档在阅读此内容后一直在说这一点。感谢您的精彩回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-02
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 2014-07-22
    • 2018-06-01
    相关资源
    最近更新 更多