开玩笑的异步测试通知测试以失败告终

时间:2018-07-27 11:14:03

标签: unit-testing asynchronous promise jestjs moxios

我有以下测试用例,当我期望测试被标记为失败时,两个测试用例都通过了:

// testing.test.js
describe('test sandbox', () => {
  it('asynchronous test failure', done => {
    Promise.resolve()
      .then(_ => {
        // failure
        expect(false).toBeTruthy();// test failed
        done();// never get called
      })
      .catch(err => {// this catches the expectation failure and finishes the test
        done(err); 
      });
  });
  it('asynchronous test success', done => {
    Promise.resolve()
      .then(_ => {
        // failure
        expect(true).toBeTruthy();
        done();
      })
      .catch(err => {
        console.log(err);
        done(err);
      });
  });
});

现在输出如下:

 PASS  src\tests\testing.test.js
  test sandbox
    √ asynchronous test failure (3ms)
    √ asynchronous test success (1ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        3.884s
Ran all test suites matching /testing.test/.

  console.log src\tests\testing.test.js:10
    { Error: expect(received).toBeTruthy()

    Expected value to be truthy, instead received
      false
        at Promise.resolve.then._ (C:\dev\reactjs\OmniUI\src\tests\testing.test.js:6:21)
        at <anonymous>
        at process._tickCallback (internal/process/next_tick.js:188:7) matcherResult: { message: [Function], pass: false } }

这是它的开始方式,当我第一次遇到它时,它停止了对其他任何有错误测试的测试,

// sandbox test
describe('test sandbox', () => {
  it('asynchronous test failure', done => {
    Promise.resolve()
      .then(_ => {
        // failure
        expect(false).toBeTruthy();
        done();// expected this to be called, but no
      })
  });
  it('asynchronous test success', done => {
    Promise.resolve()
      .then(_ => {
        // failure
        expect(true).toBeTruthy();
        done();
      })
  });
});

会停止测试套件,但效果不佳,因为我希望使用x失败的结果完成整个测试套件:

 RUNS  src/tests/testing.test.js
C:\dev\reactjs\OmniUI\node_modules\react-scripts\scripts\test.js:20
  throw err;
  ^

Error: expect(received).toBeTruthy()

Expected value to be truthy, instead received
  false
    at Promise.resolve.then._ (C:\dev\reactjs\OmniUI\src\tests\testing.test.js:6:21)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

并在Jest控制台日志中:

{
    "resource": "/C:/dev/.../src/tests/testing.test.js",
    "owner": "Jest",
    "code": "undefined",
    "severity": 8,
    "message": "Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.",
    "source": "Jest",
    "startLineNumber": 9,
    "startColumn": 1,
    "endLineNumber": 9,
    "endColumn": 6
}

这是

// real life example
// actions.js with axios call
export const startTransactionStarted = () => ({
  type: 'START_CART_TRANSACTION_STARTED',
});
export const startTransactionFinished = (payload, success) => ({
  type: 'START_CART_TRANSACTION_FINISHED',
  payload,
  success,
});
export const startTransaction = () => (dispatch, getState) => {
  const state = getState();
  const {
    transaction: { BasketId = undefined },
  } = state;
  if (BasketId !== undefined && BasketId !== null) {
    // we already have BasketId carry on without dispatching transaction actions
    return Promise.resolve();
  }

  dispatch(startTransactionStarted());

  return Axios.post("https://test:181/api/Basket/StartTransaction", {})
    .then(response => {
      const {
        data: { BusinessErrors, MessageHeader },
      } = response;
      if (BusinessErrors !== null) {
        dispatch(startTransactionFinished(BusinessErrors, false));
        return Promise.reject(BusinessErrors);
      }
      dispatch(startTransactionFinished(MessageHeader, true));
      return Promise.resolve(response.data);
    })
    .catch(error => {
      // console.log("Axios.post().catch()", error);
      dispatch(startTransactionFinished([error], false));
      /* eslint-disable prefer-promise-reject-errors */
      return Promise.reject([error]);
    });
};


// actions.test.js
import Axios from 'axios';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import moxios from 'moxios';
import {
    startTransactionStarted, 
    startTransaction, 
    startTransactionFinished
} from 'actions';

const createMockStore = configureMockStore([thunk]);

describe('actions.js', () => {
  it('test 404 response', done => {
    // create mocked store with least amount of data (only those that are needed by tested code)
    const store = createMockStore({
      transaction: {
        BasketId: null,
      },
    });

    // jest mocked function - we are using it to test that dispatch action worked
    const onFulfilled = jest.fn();
    const onErrorCalled = jest.fn();

    const error = { message: '404 - Error' };
    const expectedResponse = [error];
    // single test with mock adapter (for axios)
    moxios.withMock(() => {
      // dispatch action with axios call, pass mocked response handler
      store
        .dispatch(startTransaction())
        .then(onFulfilled)
        .catch(onErrorCalled);
      // wait for request
      moxios.wait(() => {
        // pick most recent request which then we will "mock"
        const request = moxios.requests.mostRecent();
        console.log('moxios.wait()');
        request
          .respondWith({
            status: 404,
            error,
          })
          .then(() => {
            console.log('- then()');

            expect(onFulfilled).not.toHaveBeenCalled();
            expect(onErrorCalled).toHaveBeenCalled();

            const actions = store.getActions();
            console.log(actions);
            expect(actions).toEqual([
              startTransactionStarted(),
              startTransactionFinished(expectedResponse, false),
            ]);// this fails
            done();// this is never called
          })
      });
    });
  });
});

测试因此错误而停止

 RUNS  src/tests/testing.test.js
C:\dev\reactjs\OmniUI\node_modules\react-scripts\scripts\test.js:20
  throw err;
  ^

Error: expect(received).toEqual(expected)

Expected value to equal:
  [{"type": "START_CART_TRANSACTION_STARTED"}, {"payload": [{"message": "404 - Error"}], "success": false, "type": "START_CART_TRANSACTION_FINISHED"}]
Received:
  [{"type": "START_CART_TRANSACTION_STARTED"}, {"payload": [[Error: Request failed with status code 404]], "success": false, "type": "START_CART_TRANSACTION_FINISHED"}]

Difference:

- Expected
+ Received

@@ -2,13 +2,11 @@
   Object {
     "type": "START_CART_TRANSACTION_STARTED",
   },
   Object {
     "payload": Array [
-      Object {
-        "message": "404 - Error",
-      },
+      [Error: Request failed with status code 404],
     ],
     "success": false,
     "type": "START_CART_TRANSACTION_FINISHED",
   },
 ]
    at request.respondWith.then (C:\dev\reactjs\OmniUI\src\tests\testing.test.js:101:27)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

是否有一种方法可以使异步测试(第一个示例)通过done但通知Jest它失败了?或设置玩笑以免在超时时停止进一步的测试?

0 个答案:

没有答案