简体   繁体   English

为什么这个chai-as-promised AssertionError打印到Console而不是我的Mocha测试运行器?

[英]Why is this chai-as-promised AssertionError printing to the Console but not my Mocha test runner?

I'm tyring to test some code that uses Promises with chai-as-promised and Mocha . 我正在测试一些使用Promise和chai-as-promised promise和Mocha My test suite is also utilizing fetch-mock to mock AJAX requests that would normally be sent using the Fetch API. 我的测试套件也使用fetch-mock来模拟通常使用Fetch API发送的AJAX请求。

Here's the code I'm trying to test: 这是我要测试的代码:

/**
 * 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);
        }
      });
    });
}

In my most upper-level describe , I have this function that initially sets up my fetchMock object. 在我最上层的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
      }
    }
  });
});

and here's the relevant test code: 这是相关的测试代码:

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');
  });
});

The reason I'm defining the save route in the fetchMock.mock() call is I have another test that needs the save route to be redefined to return something else. 我在fetchMock.mock()调用中定义save路由的原因是我有另一个测试需要重新定义save路由以返回其他内容。

To make sure chai-as-promised is actually working and will notify me of failed tests, I wrote a failing test promise.should.eventually.be.fulfilled; 为了确保chai-as-promised实际工作并将通知我失败的测试,我写了一个失败的测试promise.should.eventually.be.fulfilled; . This will fail because the Promise returned by save will reject if the response contains Authorization , which it does. 这将失败,因为如果响应包含Authorization ,则save返回的save将拒绝。 The Chrome Console shows the AssertionError with message: expected promise to be fulfilled but it was rejected with 'Request failed , but my Mocha test-runner.html page is showing that this test passed. Chrome控制台显示带有message: expected promise to be fulfilled but it was rejected with 'Request failed的AssertionError message: expected promise to be fulfilled but it was rejected with 'Request failed ,但我的Mocha test-runner.html页面显示此测试已通过。 For some reason, chai-as-promised isn't communicating properly with Mocha. 出于某种原因,chai-as-promise没有与Mocha正确沟通。

If you'd like to see my entire project, please see this repo on Github. 如果你想看看我的整个项目,请在Github上看到这个回购

Any ideas why? 有什么想法吗?

EDIT: 编辑:

Here's my test setup code: 这是我的测试设置代码:

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

The value promise.should.eventually.be.fulfilled is a promise, which you should return so that Mocha can know when your test is over. promise.should.eventually.be.fulfilled是一个承诺, 您应该返回,以便Mocha可以知道您的测试何时结束。 I've created a small test file to simulate what you were seeing and I can completely replicate the behavior if, like you do, I just fail to return promise.should.eventually.be.fulfilled; 我已经创建了一个小的测试文件来模拟你所看到的内容,如果像你一样,我只能无法返回promise.should.eventually.be.fulfilled;我可以完全复制行为promise.should.eventually.be.fulfilled; . Here is an example that works: 这是一个有效的例子:

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

In your code you had some cleanup code at the very end of your test: fetchMock.unregisterRoute('save'); 在你的代码中,你在测试的最后有一些清理代码: fetchMock.unregisterRoute('save'); . Based on what you show, I'd move this to an after hook so that it mirrors your before hook. 根据你所展示的内容,我将它移动到一个after钩子,以便它反映你before钩子。 In general, after should perform cleanup that corresponds to what is in before and afterEach to what is in beforeEach . 在一般情况下, after应执行对应于什么是清理beforeafterEach什么是beforeEach However, if you need to have cleanup code inside a test for some reason, you could do: 但是,如果由于某种原因需要在测试中包含清理代码,则可以执行以下操作:

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

Unfortunately, Chai seems to return something which looks like a ES6 Promise but only partially. 不幸的是,柴似乎回归的东西看起来像ES6 Promise但只是部分。 Eventually, it will probably return a actual ES6 promise, and then you'll be able to call .finally to run cleanup code no matter what happens and have the error automatically propagate up. 最终,它可能会返回一个实际的ES6承诺,然后您将能够调用.finally运行清理代码,无论发生什么情况并且错误会自动传播。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM