Jest проверка на ошибку

Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Тестирование ошибок

JS: Продвинутое тестирование

Основные тесты, которые нужно писать, это тесты на успешные сценарии работы. Но в некоторых ситуациях код должен возвращать ошибки и их тоже бывает нужно проверять. Под ошибками понимаются ситуации, в которых код выбрасывает исключение. В чем их особенность? Посмотрите на тест:

test('boom!', () => {
  try {
    functionWithException(0);
  } catch (e) {
    expect(e).not.toBeNull();
  }
});

Этот код пытается протестировать ситуацию, при которой функция functionWithException() выбрасывает исключение, если ей передать 0. Как вы думаете, этот тест проверит, что функция действительно порождает исключение?

Правильный ответ — нет. Если функция functionWithException() не выбросит исключение, то тест пройдет, так как код не попадет в блок catch.

Документация Jest предлагает свой способ тестирования таких ситуаций. Jest позволяет указать количество утверждений, которые должны выполниться в тесте. Если этого не происходит, то Jest сообщает об ошибке:

test('boom!', () => {
  // Количество утверждений, которые должны быть запущены в этом тесте
  expect.assertions(1);

  try {
    functionWithException(0);
  } catch (e) {
    expect(e).not.toBeNull();
  }
});

Этот способ крайне опасен. Он порождает хрупкие тесты, которые завязаны на то, как они написаны. Если вы захотите добавить новое утверждение, то тест провалится и придется его править. Вам всегда придется следить за тем, чтобы это число было правильным. Не используйте этот подход, чем больше контекстной зависимости, тем сложнее разобраться в коде и проще наделать ошибок.

И наконец-то мы подобрались к правильному способу. В Jest есть матчер, который самостоятельно отлавливает исключение и проверяет, что оно вообще было сгенерировано.

test('boom!', () => {
  expect(() => {
    functionWithException(0);
  }).toThrow();
});

Главная особенность этого матчера в том, что он принимает на вход функцию, которая вызывается внутри. Благодаря этому, он может самостоятельно отследить появление исключения. Этот код не содержит неявного состояния и лишних проверок, он делает ровно то, что нужно делать и не требует от нас слишком много. Более того, теоретически возможен тест, в котором делается сразу несколько проверок на различные исключения. Это значительно сложнее провернуть с предыдущими способами.

Иногда важно не просто поймать исключение, но и убедиться в том, что это ожидаемое исключение. Сделать это можно, передав в матчер toThrow() строку, которая должна присутствовать в сообщении исключения.

test('boom!', () => {
  expect(() => {
    functionWithException(0);

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно


  • 130 курсов, 2000+ часов теории

  • 1000 практических заданий в браузере

  • 360 000 студентов

Наши выпускники работают в компаниях:

Рекомендуемые программы

профессия


от 6 300 ₽ в месяц

Разработка фронтенд-компонентов для веб-приложений

профессия


от 6 300 ₽ в месяц

Разработка бэкенд-компонентов для веб-приложений

профессия


от 10 080 ₽ в месяц

Разработка фронтенд- и бэкенд-компонентов для веб-приложений

Автоматизированное тестирование веб-приложений на JavaScript

в разработке

дата определяется

In Jest you have to pass a function into expect(function).toThrow(<blank or type of error>).

Example:

test("Test description", () => {
  const t = () => {
    throw new TypeError();
  };
  expect(t).toThrow(TypeError);
});

Or if you also want to check for error message:

test("Test description", () => {
  const t = () => {
    throw new TypeError("UNKNOWN ERROR");
  };
  expect(t).toThrow(TypeError);
  expect(t).toThrow("UNKNOWN ERROR");
});

If you need to test an existing function whether it throws with a set of arguments, you have to wrap it inside an anonymous function in expect().

Example:

test("Test description", () => {
  expect(() => {http.get(yourUrl, yourCallbackFn)}).toThrow(TypeError);
});

answered Sep 11, 2017 at 12:06

PeterDanis's user avatar

PeterDanisPeterDanis

8,3402 gold badges13 silver badges23 bronze badges

10

It is a little bit weird, but it works and IMHO is good readable:

it('should throw Error with message \'UNKNOWN ERROR\' when no parameters were passed', () => {
  try {
      throwError();
      // Fail test if above expression doesn't throw anything.
      expect(true).toBe(false);
  } catch (e) {
      expect(e.message).toBe("UNKNOWN ERROR");
  }
});

The Catch block catches your exception, and then you can test on your raised Error. Strange expect(true).toBe(false); is needed to fail your test if the expected Error will be not thrown. Otherwise, this line is never reachable (Error should be raised before them).

@Kenny Body suggested a better solution which improve a code quality if you use expect.assertions():

it('should throw Error with message \'UNKNOWN ERROR\' when no parameters were passed', () => {
  expect.assertions(1);
  try {
      throwError();
  } catch (e) {
      expect(e.message).toBe("UNKNOWN ERROR");
  }
});

See the original answer with more explanations: How to test the type of a thrown exception in Jest

EDIT 2022:

To use this approach and not trigger no-conditional-expect rule (if you’re using eslint-plugin-jest), documentation of this rule suggest to use error wrapper:

class NoErrorThrownError extends Error {}

const getError = async <TError>(call: () => unknown): Promise<TError> => {
  try {
    await call();

    throw new NoErrorThrownError();
  } catch (error: unknown) {
    return error as TError;
  }
};

describe('when the http request fails', () => {
  it('includes the status code in the error', async () => {
    const error = await getError(async () => makeRequest(url));

    // check that the returned error wasn't that no error was thrown
    expect(error).not.toBeInstanceOf(NoErrorThrownError);
    expect(error).toHaveProperty('statusCode', 404);
  });
});

See: no-conditional-expect docs

answered Mar 27, 2018 at 12:31

Paweł BB Drozd's user avatar

Paweł BB DrozdPaweł BB Drozd

4,5234 gold badges21 silver badges17 bronze badges

10

I use a slightly more concise version:

expect(() => {
  // Code block that should throw error
}).toThrow(TypeError) // Or .toThrow('expectedErrorMessage')

Peter Mortensen's user avatar

answered May 23, 2019 at 8:46

Tal Joffe's user avatar

Tal JoffeTal Joffe

5,3774 gold badges25 silver badges31 bronze badges

0

From my (albeit limited) exposure to Jest, I have found that expect().toThrow() is suitable if you want to only test an error is thrown of a specific type:

expect(() => functionUnderTest()).toThrow(TypeError);

Or an error is thrown with a specific message:

expect(() => functionUnderTest()).toThrow('Something bad happened!');

If you try to do both, you will get a false positive. For example, if your code throws RangeError('Something bad happened!'), this test will pass:

expect(() => functionUnderTest()).toThrow(new TypeError('Something bad happened!'));

The answer by bodolsog which suggests using a try/catch is close, but rather than expecting true to be false to ensure the expect assertions in the catch are hit, you can instead use expect.assertions(2) at the start of your test where 2 is the number of expected assertions. I feel this more accurately describes the intention of the test.

A full example of testing the type and message of an error:

describe('functionUnderTest', () => {
    it('should throw a specific type of error.', () => {
        expect.assertions(2);

        try {
            functionUnderTest();
        } catch (error) {
            expect(error).toBeInstanceOf(TypeError);
            expect(error).toHaveProperty('message', 'Something bad happened!');
        }
    });
});

If functionUnderTest() does not throw an error, the assertions will be be hit, but the expect.assertions(2) will fail and the test will fail.

Peter Mortensen's user avatar

answered Sep 25, 2019 at 17:27

Kenny Body's user avatar

Kenny BodyKenny Body

1,0698 silver badges5 bronze badges

5

I manage to combine some answers and end up with this:

it('should throw', async () => {
    await expect(service.methodName('some@email.com', 'unknown')).rejects.toThrow(
      HttpException,
    );
  });

answered Jul 28, 2021 at 8:37

Douglas Caina's user avatar

2

Modern Jest allows you to make more checks on a rejected value. For example, you could test status code of http exception:

const request = Promise.reject({statusCode: 404})
await expect(request).rejects.toMatchObject({ statusCode: 500 });

will fail with error

Error: expect(received).rejects.toMatchObject(expected)

- Expected
+ Received

  Object {
-   "statusCode": 500,
+   "statusCode": 404,
  }

answered Oct 10, 2019 at 15:50

Slava Baginov's user avatar

Slava BaginovSlava Baginov

9691 gold badge8 silver badges10 bronze badges

2

Further to Peter Danis’ post, I just wanted to emphasize the part of his solution involving «[passing] a function into expect(function).toThrow(blank or type of error)».

In Jest, when you test for a case where an error should be thrown, within your expect() wrapping of the function under testing, you need to provide one additional arrow function wrapping layer in order for it to work. I.e.

Wrong (but most people’s logical approach):

expect(functionUnderTesting();).toThrow(ErrorTypeOrErrorMessage);

Right:

expect(() => { functionUnderTesting(); }).toThrow(ErrorTypeOrErrorMessage);

It’s very strange, but it should make the testing run successfully.

Peter Mortensen's user avatar

answered May 24, 2020 at 7:05

Adrian's user avatar

AdrianAdrian

1,68310 silver badges6 bronze badges

4

In case you are working with Promises:

await expect(Promise.reject(new HttpException('Error message', 402)))
  .rejects.toThrowError(HttpException);

answered Jan 28, 2020 at 22:30

Željko Šević's user avatar

Željko ŠevićŽeljko Šević

3,7732 gold badges26 silver badges23 bronze badges

2

Check out toThrow method.

You must wrap the code in an additional function callback!

You should check both: the error message and its type.

For example:

// additional function wrap
const wrap = () => {
  yourCodeToTest();
};

// test error message
expect(wrap).toThrow('UNKNOWN ERROR');

// test error type
expect(wrap).toThrow(TypeError);

Because of additional callback wrap, the code will not be run immediately, so jest will be able to catch it.

You should always check the error message to be sure you are checking the correct throw case and not getting another error your code may throw.

It is also nice to check the error type, so the client code may rely on it.

answered May 10, 2021 at 3:48

Igor Sukharev's user avatar

1

There’s a way to wait an error that comes from a async function, you just have to write your code like in the example bellow

await expect(yourAsyncFunction()).rejects.toThrowError();

answered Jul 7, 2022 at 18:53

Hiran Júnior's user avatar

You must wrap the code of the function that you are expecting in another arrow function, otherwise the error will not be caught and the assertion will fail.

the function you want to test :

const testThrowingError = () => {
    throw new Error();
  };

the test:

describe("error function should Throw Error", () => {
  expect(() =>testThrowingError()).toThrowError();
});

resource:
https://jestjs.io/docs/expect#tothrowerror

answered Jul 4, 2022 at 13:50

Safi Habhab's user avatar

Safi HabhabSafi Habhab

98110 silver badges17 bronze badges

I haven’t tried it myself, but I would suggest using Jest’s toThrow assertion. So I guess your example would look something like this:

it('should throw Error with message \'UNKNOWN ERROR\' when no parameters were passed', (t) => {
  const error = t.throws(() => {
    throwError();
  }, TypeError);

  expect(t).toThrowError('UNKNOWN ERROR');
  //or
  expect(t).toThrowError(TypeError);
});

Again, I haven’t test it, but I think it should work.

Peter Mortensen's user avatar

answered Sep 4, 2017 at 18:48

Andrei CACIO's user avatar

Andrei CACIOAndrei CACIO

2,10115 silver badges28 bronze badges

I have successfully used this

await expect(
      async () => await apiCalls()
    ).rejects.toThrow();

answered Feb 28, 2022 at 20:00

Liu Hantao's user avatar

Liu HantaoLiu Hantao

6181 gold badge9 silver badges19 bronze badges

Jest has a method, toThrow(error), to test that a function throws when it is called.

So, in your case you should call it so:

expect(t).toThrowError(TypeError);

The documentation.

Peter Mortensen's user avatar

answered Sep 4, 2017 at 18:49

alexmac's user avatar

alexmacalexmac

19.1k7 gold badges58 silver badges69 bronze badges

1

The documentation is clear on how to do this. Let’s say I have a function that takes two parameters and it will throw an error if one of them is null.

function concatStr(str1, str2) {
  const isStr1 = str1 === null
  const isStr2 = str2 === null
  if(isStr1 || isStr2) {
    throw "Parameters can't be null"
  }
  ... // Continue your code

Your test

describe("errors", () => {
  it("should error if any is null", () => {
    // Notice that the expect has a function that returns the function under test
    expect(() => concatStr(null, "test")).toThrow()
  })
})

Peter Mortensen's user avatar

answered Dec 14, 2019 at 15:12

redeemefy's user avatar

redeemefyredeemefy

4,5416 gold badges36 silver badges52 bronze badges

There is also an easier way to assert against the error message. The beauty of this method is that you don’t need to reconstruct the error object or to have the full error message. As long as your error contains part of the error message we can assume that it is of the correct type. i.e

 const printOnlyString = (str) => {
   if(typeof str !== "string"){
     throw Error("I can only print strings ${typeof str) given");
   }
   else {
     console.log(str);
   } 
 }

expect(() => printOnlyString(123)).toThrow(/can only print strings/)

answered Oct 21, 2022 at 16:08

Yasin Yaqoobi's user avatar

Yasin YaqoobiYasin Yaqoobi

1,9183 gold badges27 silver badges38 bronze badges

1

I ended up writing a convenience method for our test-utils library

/**
 *  Utility method to test for a specific error class and message in Jest
 * @param {fn, expectedErrorClass, expectedErrorMessage }
 * @example   failTest({
      fn: () => {
        return new MyObject({
          param: 'stuff'
        })
      },
      expectedErrorClass: MyError,
      expectedErrorMessage: 'stuff not yet implemented'
    })
 */
  failTest: ({ fn, expectedErrorClass, expectedErrorMessage }) => {
    try {
      fn()
      expect(true).toBeFalsy()
    } catch (err) {
      let isExpectedErr = err instanceof expectedErrorClass
      expect(isExpectedErr).toBeTruthy()
      expect(err.message).toBe(expectedErrorMessage)
    }
  }

answered Jun 20, 2019 at 8:31

kpollock's user avatar

kpollockkpollock

3,9099 gold badges42 silver badges62 bronze badges

2

To test whether a function throws a specific error message with a specific type of error, you can use Jest’s toThrow() matcher

function myFunction() {
  throw new TypeError('Something went wrong');
}

describe('myFunction', () => {
  it('should throw a TypeError with a specific error message', () => {
    expect(myFunction).toThrow(TypeError);
    expect(myFunction).toThrow(/Something went wrong/);

    //noted: this way will invoke the myFunction twice
    expect(myFunction).toBeCalledTimes(2)
  });
});

If you use expect(myFunction).toThrow(new TypeError("Something went wrong"), it only checks the error message rather than the error type, which does not meet the test purpose.

answered Apr 28 at 2:45

Kaiwen Luo's user avatar

Kaiwen LuoKaiwen Luo

3804 silver badges10 bronze badges

A good way is to create custom error classes and mock them. Then you can assert whatever you want.

MessedUpError.ts

type SomeCrazyErrorObject = {
  [key: string]: unknown,
}

class MessedUpError extends Error {
  private customErrorData: SomeCrazyErrorObject = {};

  constructor(err?: string, data?: SomeCrazyErrorObject) {
    super(err || 'You messed up');

    Object.entries(data ?? {}).forEach(([Key, value]) => {
      this.customErrorData[Key] = value;
    });
    Error.captureStackTrace(this, this.constructor);
  }

  logMe() {
    console.log(this.customErrorData);
  }
}

export default MessedUpError;

messedUpError.test.ts

import MessedUpError from './MessedUpError';

jest.mock('./MessedUpError', () => jest.fn().mockImplementation((...args: any[]) => ({
  constructor: args,
  log: () => {},
})));

type MessedUpErrorContructorParams = Expand<typeof MessedUpError['prototype']>
const MessedUpErrorMock = MessedUpError as unknown as jest.Mock<MessedUpError, [MessedUpErrorContructorParams]>;

const serverErrorContructorCall = (i = 0) => ({
  message: MessedUpErrorMock.mock.calls[i][0],
  ...MessedUpErrorMock.mock.calls[i][1] || {},
});

beforeEach(() => {
  MessedUpErrorMock.mockClear();
});

test('Should throw', async () => {
  try {
    await someFunctionThatShouldThrowMessedUpError();
  } catch {} finally {
    expect(MessedUpErrorMock).toHaveBeenCalledTimes(1);
    const constructorParams = serverErrorContructorCall();
    expect(constructorParams).toHaveProperty('message', 'You messed up');
    expect(constructorParams).toHaveProperty('customErrorProperty', 'someValue');
  }
});

The assertions always go inside the finally clause. This way it will always be asserted. Even if the test does not throw any errors.

answered Apr 1, 2022 at 13:49

Omar Omeiri's user avatar

Omar OmeiriOmar Omeiri

1,5261 gold badge17 silver badges33 bronze badges

If you want something less verbose in your tests but want to test an Error is of a class and has a certain message (or status, or any other properties), you can write a custom matcher.

We use something pretty simple, but you can extend this to include RegExp, etc.

// In jest.setup.js
expect.extend({
  toThrowErrorWithMessage: (received, errorType, message) => {
    if (!received) {
      return {
        message: () =>
          `expected error to be of type ${errorType.name} with message matching ${message}, received ${received}`,
        pass: false,
      };
    }

    if (!(received instanceof errorType)) {
      return {
        message: () => `expected error of type ${errorType} received ${received}`,
        pass: false,
      };
    }

    const validMessage = received.message && received.message.match(message);

    if (!validMessage) {
      return {
        message: () =>
          `expected error message to match "${message}", received "${received.message}"`,
        pass: false,
      };
    }

    return {
      pass: true,
      // Note: this message is for when using .not
      message: () =>
        `expected error not to be of type ${errorType.name} with message matching "${message}"`,
    };
  },
});

// In a test
expect(() => validate()).rejects.toThrowErrorWithMessage(BadRequestError, 'Oh noes')

answered Jul 8 at 13:34

Joel Tadmor's user avatar

Similar to the try/catch, if you are looking to catch an error for an async function one can also just append a .catch() to the function to be able to access error value:
await asyncFunc().catch(e => { expect(e.toString()).toBe("Error: My error message") }) or whatever functionality you are looking to test

answered Jul 25 at 17:16

super IT guy's user avatar

Jest version: 29

You have an async function that needs to be tested for throwing an error.

await expect(listener.onMessage(data, msg)).rejects.toThrow();

Assert with exact error message:

await expect(listener.onMessage(data, msg)).rejects.toThrow("Data not found!");

answered Jul 30 at 3:28

Ikram Ud Daula's user avatar

Try:

expect(t).rejects.toThrow()

Peter Mortensen's user avatar

answered May 16, 2019 at 16:37

Razim Saidov's user avatar

2

Agenda

  1. The goal of this post
  2. expect.assertions(number) rather than done()
  3. .rejects rather than try-catch
  4. .toThrow rather than toMatch or toEqual
  5. Use-case 1: Handle Error in a function
  6. Use-case 2: Handle Error in an asynchronous function
  7. References

1. The goal of this post

The goal of this post is to give you an opinionated way of how to handle error with jest. Since a bunch of source, including the official guide, suggests various ways (but each way has its own rule to comply with 😡), it would mislead to testing.

2. expect.assertions(number) rather than done()

Both expect.assertions() and done() are used to test async functions. However, expect.assertions() is focused on to verify that a certain number of assertions are called during a test while done() is focused on to wait a certain assertion to be called. Therefore, expect.assertions() would fail if the number of expectations are not called while done() would fail because of timeout (mostly from not calling done() at the end).

Let’s compare between done() and expect.assertion(number) when doing async calls.

API — expect.assertions(number)

Make sure to add expect.assertions to verify that a certain number of assertions are called. Otherwise a fulfilled promise would not fail the test.

test('doAsync calls both callbacks', () => {
  expect.assertions(2);
  function callback1(data) {
    expect(data).toBeTruthy();
  }
  function callback2(data) {
    expect(data).toBeTruthy();
  }

  doAsync(callback1, callback2);
});

Enter fullscreen mode

Exit fullscreen mode

VS.

Testing Asynchronous Code — callbacks

done() is necessary. Otherwise, the test will complete as soon as fetchData completes, before ever calling the callback.

test('the data is peanut butter', done => {
  function callback(error, data) {
    if (error) {
      done(error);
      return;
    }
    try {
      expect(data).toBe('peanut butter');
      done();
    } catch (error) {
      done(error);
    }
  }

  fetchData(callback);
});

Enter fullscreen mode

Exit fullscreen mode

You could notice at a glance that done(error) is declared in the catch block in order to avoid timeout. On the one hand, you could easily notice errors and reduce your time to figure out what went wrong by doing so. On the other hand, you could easily forget that where you need to declare done() properly.

The rule of thumbs here is to declare expect.assertions(number) at the beginning of your tests. It never causes a problem at all.

3. .rejects rather than try-catch

API — .rejects

Use .rejects to unwrap the reason of a rejected promise so any other matcher can be chained. If the promise is fulfilled the assertion fails.

test('rejects to octopus', async () => {
  await expect(Promise.reject(new Error('octopus'))).rejects.toThrow('octopus');
});

Enter fullscreen mode

Exit fullscreen mode

VS.

Stack Overflow

You must handle errors at the catch block.

it('calls the API and throws an error', async () => {
  expect.assertions(2);
  try {
    await login('email', 'password');
  } catch (error) {
    expect(error.name).toEqual('Unauthorized');
    expect(error.status).toEqual(401);
  }
});

Enter fullscreen mode

Exit fullscreen mode

You know the test is supposed to cause an error. The key point of .rejects() is that the assertion fails when the promise is fulfilled.

!CAUTION
Be sure to return (or await) the promise — if you omit the return/await statement, your test will complete before the promise returned from fetchData resolves or rejects.

!tip
expect.assertions(number) while using .rejects is not required but recommended to verify that a certain number of assertions are called during a test.

4. .toThrow rather than toMatch or toEqual

You can provide an optional argument to test that a specific error is thrown such as regex, string, error object, and error class. However, toMatch and toEqual only do one thing each: to match a string and equal to an object.

API — .toThrow

test('throws on octopus', () => {
  expect(() => {
    drinkFlavor('octopus');
  }).toThrow();
});

Enter fullscreen mode

Exit fullscreen mode

Stack Overflow

test("Test description", () => {
  const t = () => {
    throw new TypeError("UNKNOWN ERROR");
  };
  expect(t).toThrow(TypeError);
  expect(t).toThrow("UNKNOWN ERROR");
});

Enter fullscreen mode

Exit fullscreen mode

!tip
You must wrap the code in a function, otherwise the error will not be caught and the assertion will fail.

!tip
You don’t need to wrap a promise function. Just invoke it.
Code Example

test('the fetch fails with an error', async () => {
  await expect(fetchData()).rejects.toMatch('error');
});

Enter fullscreen mode

Exit fullscreen mode

5. Use-case 1: Handle Error in a function

Let’s integrate what we learned into a simple code snippet.

test("Test description", () => {
  expect.assertions(2);
  const t = () => {
    throw new TypeError("UNKNOWN ERROR");
  };
  expect(t).toThrow(TypeError);
  expect(t).toThrow("UNKNOWN ERROR");
});

Enter fullscreen mode

Exit fullscreen mode

  • I declared expect.assertions(number) even though the above test is not asynchronous. It doesn’t matter since expect.assertions() never causes a problem at all.
  • I used .toThrow() rather than .toMatch or .toEqual since it handles Error object and string alike.

6. Use-case 2: Handle Error in an asynchronous function

test('the fetch fails with an error', async () => {
  expect.assertions(1);
  await expect(fetchData()).rejects.toThrow('error');
});

Enter fullscreen mode

Exit fullscreen mode

  • I declared expect.assertions(number) even though it is not required while using .rejects().
  • I handled an error, by using .rejects, within a single block, not within a try-catch block.
  • I used .toThrow rather than .toMatch or .toEqual.

7. References

  • Jest API — expect
  • Jest Guide — An Async Example
  • Jest Introduction — Testing Asynchronous Code
  • How to test the type of a thrown exception in Jest
  • Necessary to use expect.assertions() if you’re awaiting any async function calls?
  • Can you write async tests that expect toThrow?
  • Writing Good Assertions

Whenever you are looking to test an error thrown by a function in Jest, you want to pass the function to the expect, rather than invoking the function. Take a look at the following examples:

const functionWithError = param => {  
    throw new Error()
}

it('should throw an error', () => {
    expect(functionWithError).toThrow(Error)
})

Copied to clipboard!

We have a mock function and we want to test whether it throws the error we are expecting. We can do this by simply passing the function to the expect without actually invoking it, and calling the toThrow method on it with the passed error.

But what if you have to call the function, for example, to provide parameters? In this case, you can wrap the function into an anonymous function:

// 🟢 Do
expect(() => functionWithError()).toThrow(Error)

// 🔴 Don’t
expect(functionWithError()).toThrow(Error)
expect(functionWithError('param')).toThrow(Error)

Copied to clipboard!

Notice that if you try to call the function directly inside the expect, it will fail the test as the error is not caught and the assertion will fail. You can also test other types of errors by passing the correct error to toThrow:

expect(functionWithError()).toThrow(EvalError)
expect(functionWithError()).toThrow(RangeError)
expect(functionWithError()).toThrow(ReferenceError)
expect(functionWithError()).toThrow(SyntaxError)
expect(functionWithError()).toThrow(TypeError)
expect(functionWithError()).toThrow(URIError)
expect(functionWithError()).toThrow(AggregateError)

Pass the correct type of error to test different types

Copied to clipboard!

Lastly, if you would like to test the error message itself, toThrow also accepts a string so you can test both the type and message:

const functionWithError = () => {
    throw new TypeError('Custom Error')
}

it('should throw an error', () => {
    expect(functionWithError).toThrow(TypeError)
    expect(functionWithError).toThrow('Custom Error')
})

Copied to clipboard!

How to Mock process.env in Jest

How to Mock process.env in JestUnit testing environment-specific parts in your applicationLearn how you can properly mock environment variables in your Jest tests to correctly test environment-specific parts in your application.

Когда вы пишете тесты, вам часто нужно проверить, соответствуют ли значения определенным условиям. expect дает вам доступ к ряду «сопоставителей», которые позволяют вам проверять разные вещи.

Чтобы узнать о дополнительных сопоставителях Jest, поддерживаемых сообществом Jest, ознакомьтесь с jest-extended .

Methods

  • expect(value)
  • expect.extend(matchers)
  • expect.anything()
  • expect.any(constructor)
  • expect.arrayContaining(array)
  • expect.assertions(number)
  • expect.closeTo(number, numDigits?)
  • expect.hasAssertions()
  • expect.not.arrayContaining(array)
  • expect.not.objectContaining(object)
  • expect.not.stringContaining(string)
  • expect.not.stringMatching(string | regexp)
  • expect.objectContaining(object)
  • expect.stringContaining(string)
  • expect.stringMatching(string | regexp)
  • expect.addSnapshotSerializer(serializer)
  • .not
  • .resolves
  • .rejects
  • .toBe(value)
  • .toHaveBeenCalled()
  • .toHaveBeenCalledTimes(number)
  • .toHaveBeenCalledWith(arg1, arg2, ...)
  • .toHaveBeenLastCalledWith(arg1, arg2, ...)
  • .toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....)
  • .toHaveReturned()
  • .toHaveReturnedTimes(number)
  • .toHaveReturnedWith(value)
  • .toHaveLastReturnedWith(value)
  • .toHaveNthReturnedWith(nthCall, value)
  • .toHaveLength(number)
  • .toHaveProperty(keyPath, value?)
  • .toBeCloseTo(number, numDigits?)
  • .toBeDefined()
  • .toBeFalsy()
  • .toBeGreaterThan(number | bigint)
  • .toBeGreaterThanOrEqual(number | bigint)
  • .toBeLessThan(number | bigint)
  • .toBeLessThanOrEqual(number | bigint)
  • .toBeInstanceOf(Class)
  • .toBeNull()
  • .toBeTruthy()
  • .toBeUndefined()
  • .toBeNaN()
  • .toContain(item)
  • .toContainEqual(item)
  • .toEqual(value)
  • .toMatch(regexp | string)
  • .toMatchObject(object)
  • .toMatchSnapshot(propertyMatchers?, hint?)
  • .toMatchInlineSnapshot(propertyMatchers?, inlineSnapshot)
  • .toStrictEqual(value)
  • .toThrow(error?)
  • .toThrowErrorMatchingSnapshot(hint?)
  • .toThrowErrorMatchingInlineSnapshot(inlineSnapshot)

Reference

expect(value)

Функция expect используется каждый раз, когда вы хотите проверить значение. Вы редко будете вызывать expect само по себе. Вместо этого вы будете использовать expect вместе с функцией «сопоставления», чтобы что-то утверждать о значении.

Это проще понять на примере. Допустим, у вас есть метод bestLaCroixFlavor() который должен возвращать строку 'grapefruit' . Вот как это проверить:

test('the best flavor is grapefruit', () => {
  expect(bestLaCroixFlavor()).toBe('grapefruit');
});

В этом случае toBe сопоставления toBe . Существует множество различных функций сопоставления, которые описаны ниже, чтобы помочь вам тестировать разные вещи.

Аргумент expect должен быть значением , которое производит ваш код, и любой аргумент согласовани должен быть правильным значением. Если вы их перепутаете, ваши тесты все равно будут работать, но сообщения об ошибках при неудачных тестах будут выглядеть странно.

expect.extend(matchers)

Вы можете использовать expect.extend , чтобы добавлять в Jest собственные сопоставления. Например, предположим, что вы тестируете библиотеку утилит для чисел и часто утверждаете, что числа появляются в определенных диапазонах других чисел. Вы можете абстрагировать это в сопоставлении toBeWithinRange :

expect.extend({
  toBeWithinRange(received, floor, ceiling) {
    const pass = received >= floor && received <= ceiling;
    if (pass) {
      return {
        message: () =>
          `expected ${received} not to be within range ${floor} - ${ceiling}`,
        pass: true,
      };
    } else {
      return {
        message: () =>
          `expected ${received} to be within range ${floor} - ${ceiling}`,
        pass: false,
      };
    }
  },
});

test('numeric ranges', () => {
  expect(100).toBeWithinRange(90, 110);
  expect(101).not.toBeWithinRange(0, 100);
  expect({apples: 6, bananas: 3}).toEqual({
    apples: expect.toBeWithinRange(1, 10),
    bananas: expect.not.toBeWithinRange(11, 20),
  });
});

note

Например, в TypeScript при использовании @types/jest вы можете объявить новый toBeWithinRange в импортированном модуле следующим образом:

interface CustomMatchers<R = unknown> {
  toBeWithinRange(floor: number, ceiling: number): R;
}

declare global {
  namespace jest {
    interface Expect extends CustomMatchers {}
    interface Matchers<R> extends CustomMatchers<R> {}
    interface InverseAsymmetricMatchers extends CustomMatchers {}
  }
}

Async Matchers

expect.extend также поддерживает асинхронные сопоставления. Асинхронные сопоставители возвращают обещание, поэтому вам нужно будет дождаться возвращенного значения. Давайте использовать пример сопоставления, чтобы проиллюстрировать их использование. Мы собираемся реализовать сопоставление под названием toBeDivisibleByExternalValue , где делимое число будет извлекаться из внешнего источника.

expect.extend({
  async toBeDivisibleByExternalValue(received) {
    const externalValue = await getExternalValueFromRemoteSource();
    const pass = received % externalValue == 0;
    if (pass) {
      return {
        message: () =>
          `expected ${received} not to be divisible by ${externalValue}`,
        pass: true,
      };
    } else {
      return {
        message: () =>
          `expected ${received} to be divisible by ${externalValue}`,
        pass: false,
      };
    }
  },
});

test('is divisible by external value', async () => {
  await expect(100).toBeDivisibleByExternalValue();
  await expect(101).not.toBeDivisibleByExternalValue();
});

API пользовательских матчей

Сопоставители должны возвращать объект (или обещание объекта) с двумя ключами. pass указывает, было совпадение или нет, а message предоставляет функцию без аргументов, которая возвращает сообщение об ошибке в случае сбоя. Таким образом, когда pass имеет значение false, message должно возвращать сообщение об ошибке, когда expect(x).yourMatcher() терпит неудачу. И когда pass имеет значение true, message должно возвращать сообщение об ошибке, когда expect(x).not.yourMatcher() терпит неудачу.

Сопоставители вызываются с аргументом, переданным в expect(x) за которым следуют аргументы, переданные в .yourMatcher(y, z) :

expect.extend({
  yourMatcher(x, y, z) {
    return {
      pass: true,
      message: () => '',
    };
  },
});

Эти вспомогательные функции и свойства могут быть найдены на this внутри пользовательской согласовани:

this.isNot

.not значение, чтобы вы знали, что этот сопоставитель был вызван с модификатором negated .not , позволяющим отображать четкую и правильную подсказку сопоставления (см. Пример кода).

this.promise

Строка,позволяющая отобразить четкую и правильную подсказку о матчере:

  • 'rejects' , если сопоставление было .rejects модификатором обещания .rejects
  • 'resolves' если сопоставление было .resolves модификатором обещания .resolves
  • '' если сопоставление не было вызвано с модификатором обещания

this.equals(a, b)

Это функция глубокого равенства, которая вернет true если два объекта имеют одинаковые значения (рекурсивно).

this.expand

Логический , чтобы вы знали это согласовань была вызвана с expand опции. Когда Jest вызывается с флагом --expand , this.expand может использоваться, чтобы определить, должен ли Jest показывать полные различия и ошибки.

this.utils

На this.utils есть ряд полезных инструментов, в основном состоящих из экспорта из jest-matcher-utils .

Наиболее полезными из них являются matcherHint , printExpected и printReceived для удобного форматирования сообщений об ошибках. Например, посмотрите на реализацию toBe :

const {diff} = require('jest-diff');
expect.extend({
  toBe(received, expected) {
    const options = {
      comment: 'Object.is equality',
      isNot: this.isNot,
      promise: this.promise,
    };

    const pass = Object.is(received, expected);

    const message = pass
      ? () =>
          
          this.utils.matcherHint('toBe', undefined, undefined, options) +
          '\n\n' +
          `Expected: not ${this.utils.printExpected(expected)}\n` +
          `Received: ${this.utils.printReceived(received)}`
      : () => {
          const diffString = diff(expected, received, {
            expand: this.expand,
          });
          return (
            
            this.utils.matcherHint('toBe', undefined, undefined, options) +
            '\n\n' +
            (diffString && diffString.includes('- Expect')
              ? `Difference:\n\n${diffString}`
              : `Expected: ${this.utils.printExpected(expected)}\n` +
                `Received: ${this.utils.printReceived(received)}`)
          );
        };

    return {actual: received, message, pass};
  },
});

Это напечатает что-то вроде этого:

  expect(received).toBe(expected)

    Expected value to be (using Object.is):
      "banana"
    Received:
      "apple"

Когда утверждение не удается,сообщение об ошибке должно давать столько сигнала,сколько необходимо пользователю,чтобы он мог быстро решить свою проблему.Вы должны создать точное сообщение об ошибке,чтобы убедиться,что пользователи ваших пользовательских утверждений имеют хороший опыт работы с разработчиками.

Пользовательские снимки матчей

Чтобы использовать тестирование снимков внутри вашего настраиваемого сопоставителя, вы можете импортировать jest-snapshot и использовать его из своего сопоставителя.

Вот средство сопоставления снимков, которое обрезает строку для сохранения заданной длины, .toMatchTrimmedSnapshot(length) :

const {toMatchSnapshot} = require('jest-snapshot');

expect.extend({
  toMatchTrimmedSnapshot(received, length) {
    return toMatchSnapshot.call(
      this,
      received.substring(0, length),
      'toMatchTrimmedSnapshot',
    );
  },
});

it('stores only 10 characters', () => {
  expect('extra long string oh my gerd').toMatchTrimmedSnapshot(10);
});

Также можно создавать пользовательские матчики для инлайн-снимков,при этом снимки будут корректно добавляться в пользовательские матчики.Однако inline snapshot всегда будет пытаться добавлять к первому аргументу или второму,если первый аргумент-это property matcher,поэтому невозможно принимать пользовательские аргументы в пользовательских matchers.

const {toMatchInlineSnapshot} = require('jest-snapshot');

expect.extend({
  toMatchTrimmedInlineSnapshot(received, ...rest) {
    return toMatchInlineSnapshot.call(this, received.substring(0, 10), ...rest);
  },
});

it('stores only 10 characters', () => {
  expect('extra long string oh my gerd').toMatchTrimmedInlineSnapshot();
  
});

async

Если ваш пользовательский встроенный сопоставитель снимков является асинхронным, то есть использует asyncawait , вы можете столкнуться с ошибкой типа «Несколько встроенных снимков для одного и того же вызова не поддерживаются». Jest нужна дополнительная контекстная информация, чтобы найти, где пользовательское встроенное сопоставление снимков использовалось для правильного обновления снимков.

const {toMatchInlineSnapshot} = require('jest-snapshot');

expect.extend({
  async toMatchObservationInlineSnapshot(fn, ...rest) {
    
    this.error = new Error();

    
    
    const observation = await observe(async () => {
      await fn();
    });

    return toMatchInlineSnapshot.call(this, recording, ...rest);
  },
});

it('observes something', async () => {
  await expect(async () => {
    return 'async action';
  }).toMatchTrimmedInlineSnapshot();
  
});

Bail out

Обычно jest пытается сопоставить каждый снимок, который ожидается в тесте.

Иногда не имеет смысла продолжать тест,если предыдущий снимок оказался неудачным.Например,когда вы делаете снимки машины состояний после различных переходов,вы можете прервать тест,если один переход привел к неправильному состоянию.

В этом случае вы можете реализовать пользовательский snapshot matcher,который бросает при первом несоответствии вместо того,чтобы собирать каждое несоответствие.

const {toMatchInlineSnapshot} = require('jest-snapshot');

expect.extend({
  toMatchStateInlineSnapshot(...args) {
    this.dontThrow = () => {};

    return toMatchInlineSnapshot.call(this, ...args);
  },
});

let state = 'initial';

function transition() {
  
  if (state === 'INITIAL') {
    state = 'pending';
  } else if (state === 'pending') {
    state = 'done';
  }
}

it('transitions as expected', () => {
  expect(state).toMatchStateInlineSnapshot(`"initial"`);

  transition();
  
  expect(state).toMatchStateInlineSnapshot(`"loading"`);

  transition();
  expect(state).toMatchStateInlineSnapshot(`"done"`);
});

expect.anything()

expect.anything() соответствует чему угодно, кроме null или undefined . Вы можете использовать его внутри toEqual или toBeCalledWith вместо буквального значения. Например, если вы хотите проверить, что фиктивная функция вызывается с ненулевым аргументом:

test('map calls its argument with a non-null argument', () => {
  const mock = jest.fn();
  [1].map(x => mock(x));
  expect(mock).toBeCalledWith(expect.anything());
});

expect.any(constructor)

expect.any(constructor) соответствует всему, что было создано с помощью данного конструктора, или если это примитив переданного типа. Вы можете использовать его внутри toEqual или toBeCalledWith вместо буквального значения. Например, если вы хотите проверить, вызывается ли фиктивная функция с числом:

class Cat {}
function getCat(fn) {
  return fn(new Cat());
}

test('randocall calls its callback with a class instance', () => {
  const mock = jest.fn();
  getCat(mock);
  expect(mock).toBeCalledWith(expect.any(Cat));
});

function randocall(fn) {
  return fn(Math.floor(Math.random() * 6 + 1));
}

test('randocall calls its callback with a number', () => {
  const mock = jest.fn();
  randocall(mock);
  expect(mock).toBeCalledWith(expect.any(Number));
});

expect.arrayContaining(array)

expect.arrayContaining(array) соответствует полученному массиву, который содержит все элементы ожидаемого массива. То есть ожидаемый массив — это подмножество полученного массива. Следовательно, он соответствует полученному массиву, который содержит элементы, которых нет в ожидаемом массиве.

Вы можете использовать его вместо буквального значения:

  • в toEqual или toBeCalledWith
  • для соответствия свойству в objectContaining или toMatchObject
describe('arrayContaining', () => {
  const expected = ['Alice', 'Bob'];
  it('matches even if received contains additional elements', () => {
    expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(expected));
  });
  it('does not match if received does not contain expected elements', () => {
    expect(['Bob', 'Eve']).not.toEqual(expect.arrayContaining(expected));
  });
});
describe('Beware of a misunderstanding! A sequence of dice rolls', () => {
  const expected = [1, 2, 3, 4, 5, 6];
  it('matches even with an unexpected number 7', () => {
    expect([4, 1, 6, 7, 3, 5, 2, 5, 4, 6]).toEqual(
      expect.arrayContaining(expected),
    );
  });
  it('does not match without an expected number 2', () => {
    expect([4, 1, 6, 7, 3, 5, 7, 5, 4, 6]).not.toEqual(
      expect.arrayContaining(expected),
    );
  });
});

expect.assertions(number)

expect.assertions(number) проверяет, что во время теста вызывается определенное количество утверждений. Это часто бывает полезно при тестировании асинхронного кода, чтобы убедиться, что утверждения в обратном вызове действительно вызываются.

Например, предположим, что у нас есть функция doAsync , которая получает два обратных callback1 и callback2 , она будет асинхронно вызывать их оба в неизвестном порядке. Мы можем проверить это с помощью:

test('doAsync calls both callbacks', () => {
  expect.assertions(2);
  function callback1(data) {
    expect(data).toBeTruthy();
  }
  function callback2(data) {
    expect(data).toBeTruthy();
  }

  doAsync(callback1, callback2);
});

В expect.assertions(2) гарантирует , что оба вызова функции обратного вызова на самом деле вызываются.

expect.closeTo(number, numDigits?)

expect.closeTo(number, numDigits?) полезен при сравнении чисел с плавающей запятой в свойствах объекта или элементе массива. Если вам нужно сравнить число, используйте вместо него .toBeCloseTo .

Необязательный аргумент numDigits ограничивает количество проверяемых цифр после запятой. Для значения по умолчанию 2 критерием проверки является Math.abs(expected - received) < 0.005 (that is, 10 ** -2 / 2) .

Например,этот тест проходит с точностью до 5 цифр:

test('compare float in object properties', () => {
  expect({
    title: '0.1 + 0.2',
    sum: 0.1 + 0.2,
  }).toEqual({
    title: '0.1 + 0.2',
    sum: expect.closeTo(0.3, 5),
  });
});

expect.hasAssertions()

expect.hasAssertions() проверяет, что во время теста вызывается хотя бы одно утверждение. Это часто бывает полезно при тестировании асинхронного кода, чтобы убедиться, что утверждения в обратном вызове действительно вызываются.

Например, предположим, что у нас есть несколько функций, которые все имеют дело с состоянием. prepareState вызывает обратный вызов с объектом состояния, validateState запускается для этого объекта состояния, а waitOnState возвращает обещание, которое ожидает завершения всех prepareState вызовов prepareState . Мы можем проверить это с помощью:

test('prepareState prepares a valid state', () => {
  expect.hasAssertions();
  prepareState(state => {
    expect(validateState(state)).toBeTruthy();
  });
  return waitOnState();
});

В expect.hasAssertions() гарантирует , что вызов prepareState обратного вызова на самом деле вызывается.

expect.not.arrayContaining(array)

expect.not.arrayContaining(array) соответствует полученному массиву, который не содержит всех элементов ожидаемого массива. То есть ожидаемый массив не является подмножеством полученного массива.

Это противоположность expect.arrayContaining .

describe('not.arrayContaining', () => {
  const expected = ['Samantha'];

  it('matches if the actual array does not contain the expected elements', () => {
    expect(['Alice', 'Bob', 'Eve']).toEqual(
      expect.not.arrayContaining(expected),
    );
  });
});

expect.not.objectContaining(object)

expect.not.objectContaining(object) соответствует любому полученному объекту, который рекурсивно не соответствует ожидаемым свойствам. То есть ожидаемый объект не является подмножеством полученного объекта. Следовательно, он соответствует полученному объекту, который содержит свойства, которых нет в ожидаемом объекте.

Это противоположность expect.objectContaining .

describe('not.objectContaining', () => {
  const expected = {foo: 'bar'};

  it('matches if the actual object does not contain expected key: value pairs', () => {
    expect({bar: 'baz'}).toEqual(expect.not.objectContaining(expected));
  });
});

expect.not.stringContaining(string)

expect.not.stringContaining(string) соответствует полученному значению, если оно не является строкой или если это строка, не содержащая точной ожидаемой строки.

Это противоположность expect.stringContaining .

describe('not.stringContaining', () => {
  const expected = 'Hello world!';

  it('matches if the received value does not contain the expected substring', () => {
    expect('How are you?').toEqual(expect.not.stringContaining(expected));
  });
});

expect.not.stringMatching(string | regexp)

expect.not.stringMatching(string | regexp) соответствует полученному значению, если оно не является строкой или если это строка, которая не соответствует ожидаемой строке или регулярному выражению.

Это противоположность expect.stringMatching .

describe('not.stringMatching', () => {
  const expected = /Hello world!/;

  it('matches if the received value does not match the expected regex', () => {
    expect('How are you?').toEqual(expect.not.stringMatching(expected));
  });
});

expect.objectContaining(object)

expect.objectContaining(object) соответствует любому полученному объекту, который рекурсивно соответствует ожидаемым свойствам. То есть ожидаемый объект — это подмножество полученного объекта. Следовательно, он соответствует полученному объекту, который содержит свойства, присутствующие в ожидаемом объекте.

Вместо буквальных значений свойств в ожидаемом объекте вы можете использовать сопоставители, expect.anything() и т. Д.

Например, предположим, что мы ожидаем, что функция onPress будет вызвана с объектом Event , и все, что нам нужно проверить, — это наличие у события свойств event.x и event.y . Мы можем сделать это с помощью:

test('onPress gets called with the right thing', () => {
  const onPress = jest.fn();
  simulatePresses(onPress);
  expect(onPress).toBeCalledWith(
    expect.objectContaining({
      x: expect.any(Number),
      y: expect.any(Number),
    }),
  );
});

expect.stringContaining(string)

expect.stringContaining(string) соответствует полученному значению, если это строка, содержащая точную ожидаемую строку.

expect.stringMatching(string | regexp)

expect.stringMatching(string | regexp) соответствует полученному значению, если это строка, которая соответствует ожидаемой строке или регулярному выражению.

Вы можете использовать его вместо буквального значения:

  • в toEqual или toBeCalledWith
  • для соответствия элементу в arrayContaining
  • для соответствия свойству в objectContaining или toMatchObject

В этом примере также показано, как можно вложить несколько асимметричных сопоставителей с expect.stringMatching внутри expect.arrayContaining .

describe('stringMatching in arrayContaining', () => {
  const expected = [
    expect.stringMatching(/^Alic/),
    expect.stringMatching(/^[BR]ob/),
  ];
  it('matches even if received contains additional elements', () => {
    expect(['Alicia', 'Roberto', 'Evelina']).toEqual(
      expect.arrayContaining(expected),
    );
  });
  it('does not match if received does not contain expected elements', () => {
    expect(['Roberto', 'Evelina']).not.toEqual(
      expect.arrayContaining(expected),
    );
  });
});

expect.addSnapshotSerializer(serializer)

Вы можете вызвать expect.addSnapshotSerializer , чтобы добавить модуль, форматирующий структуры данных для конкретного приложения.

Для отдельного тестового файла добавленный модуль предшествует любым модулям из конфигурации snapshotSerializers , которые предшествуют сериализаторам моментальных снимков по умолчанию для встроенных типов JavaScript и для элементов React. Последний добавленный модуль — это первый протестированный модуль.

import serializer from 'my-serializer-module';
expect.addSnapshotSerializer(serializer);

Если вы добавляете сериализатор моментальных снимков в отдельные тестовые файлы вместо добавления его в конфигурацию snapshotSerializers :

  • Вы делаете зависимость явной,а не неявной.
  • Вы избегаете ограничений конфигурации, из-за которых вы можете выйти из приложения create-react-app .

См. Дополнительную информацию в разделе « Настройка Jest» .

.not

Если вы знаете, как что-то тестировать, .not позволяет вам протестировать противоположное. Например, этот код проверяет, что лучший вкус La Croix — не кокос:

test('the best flavor is not coconut', () => {
  expect(bestLaCroixFlavor()).not.toBe('coconut');
});

.resolves

Используйте resolves , чтобы развернуть значение выполненного обещания, чтобы можно было связать любой другой сопоставитель. Если обещание отклонено, утверждение не выполняется.

Например, этот код проверяет, разрешается ли обещание и что в результате получается значение 'lemon' :

test('resolves to lemon', () => {
  
  return expect(Promise.resolve('lemon')).resolves.toBe('lemon');
});

Обратите внимание, что, поскольку вы все еще тестируете обещания, тест по-прежнему асинхронный. Следовательно, вам нужно будет указать Jest подождать , вернув развернутое утверждение.

В качестве альтернативы вы можете использовать async/await в сочетании с .resolves :

test('resolves to lemon', async () => {
  await expect(Promise.resolve('lemon')).resolves.toBe('lemon');
  await expect(Promise.resolve('lemon')).resolves.not.toBe('octopus');
});

.rejects

Используйте .rejects , чтобы раскрыть причину отклоненного обещания, чтобы можно было связать любой другой сопоставитель. Если обещание выполнено, утверждение не выполняется.

Например, этот код проверяет, что обещание отклоняется по причине 'octopus' :

test('rejects to octopus', () => {
  
  return expect(Promise.reject(new Error('octopus'))).rejects.toThrow(
    'octopus',
  );
});

Обратите внимание, что, поскольку вы все еще тестируете обещания, тест по-прежнему асинхронный. Следовательно, вам нужно будет указать Jest подождать , вернув развернутое утверждение.

В качестве альтернативы вы можете использовать async/await в сочетании с .rejects .

test('rejects to octopus', async () => {
  await expect(Promise.reject(new Error('octopus'))).rejects.toThrow('octopus');
});

.toBe(value)

Используйте .toBe для сравнения примитивных значений или для проверки ссылочной идентичности экземпляров объектов. Он вызывает Object.is для сравнения значений, что даже лучше для тестирования, чем оператор строгого равенства === .

Например, этот код будет проверять некоторые свойства объекта can :

const can = {
  name: 'pamplemousse',
  ounces: 12,
};

describe('the can', () => {
  test('has 12 ounces', () => {
    expect(can.ounces).toBe(12);
  });

  test('has a sophisticated name', () => {
    expect(can.name).toBe('pamplemousse');
  });
});

Не используйте .toBe с числами с плавающей запятой. Например, из-за округления в JavaScript 0.2 + 0.1 не совсем равно 0.3 . Если у вас есть числа с плавающей запятой, попробуйте вместо этого .toBeCloseTo .

Хотя сопоставитель .toBe проверяет ссылочную идентичность, он сообщает о глубоком сравнении значений, если утверждение не выполняется. Если различия между свойствами не помогают понять, почему тест не проходит, особенно если отчет большой, то вы можете переместить сравнение в функцию expect . Например, чтобы подтвердить, являются ли элементы одним и тем же экземпляром:

  • перезаписать expect(received).toBe(expected) как ожидаемый expect(Object.is(received, expected)).toBe(true)
  • переписать expect(received).not.toBe(expected) как ожидаемый expect(Object.is(received, expected)).toBe(false)

.toHaveBeenCalled()

Также под псевдонимом: .toBeCalled()

Используйте .toHaveBeenCalledWith , чтобы убедиться, что фиктивная функция вызывается с определенными аргументами. Аргументы проверяются по тому же алгоритму, что .toEqual .

Например, предположим, что у вас есть drinkAll(drink, flavour) которая берет функцию drink и применяет ее ко всем доступным напиткам. Возможно, вы захотите проверить, называют ли drink 'lemon' , но не 'octopus' , потому что вкус 'octopus' действительно странный, и почему что-то должно быть со вкусом осьминога? Вы можете сделать это с помощью этого набора тестов:

function drinkAll(callback, flavour) {
  if (flavour !== 'octopus') {
    callback(flavour);
  }
}

describe('drinkAll', () => {
  test('drinks something lemon-flavoured', () => {
    const drink = jest.fn();
    drinkAll(drink, 'lemon');
    expect(drink).toHaveBeenCalled();
  });

  test('does not drink something octopus-flavoured', () => {
    const drink = jest.fn();
    drinkAll(drink, 'octopus');
    expect(drink).not.toHaveBeenCalled();
  });
});

.toHaveBeenCalledTimes(number)

Также под псевдонимом: .toBeCalledTimes(number)

Используйте .toHaveBeenCalledTimes , чтобы гарантировать, что фиктивная функция вызывается точное количество раз.

Например, предположим, что у вас есть drinkEach(drink, Array<flavor>) которая принимает функцию drink и применяет ее к массиву переданных напитков. Вы можете проверить, вызывалась ли функция питья точное количество раз. Вы можете сделать это с помощью этого набора тестов:

test('drinkEach drinks each drink', () => {
  const drink = jest.fn();
  drinkEach(drink, ['lemon', 'octopus']);
  expect(drink).toHaveBeenCalledTimes(2);
});

.toHaveBeenCalledWith(arg1, arg2, ...)

Также под псевдонимом: .toBeCalledWith()

Используйте .toHaveBeenCalledWith , чтобы убедиться, что фиктивная функция вызывается с определенными аргументами. Аргументы проверяются по тому же алгоритму, что .toEqual .

Например, предположим, что вы можете зарегистрировать напиток с помощью функции register , и applyToAll(f) должен применить функцию f ко всем зарегистрированным напиткам. Чтобы убедиться, что это работает, вы можете написать:

test('registration applies correctly to orange La Croix', () => {
  const beverage = new LaCroix('orange');
  register(beverage);
  const f = jest.fn();
  applyToAll(f);
  expect(f).toHaveBeenCalledWith(beverage);
});

.toHaveBeenLastCalledWith(arg1, arg2, ...)

Также под псевдонимом: .lastCalledWith(arg1, arg2, ...)

Если у вас есть .toHaveBeenLastCalledWith функция, вы можете использовать .toHaveBeenLastCalledWith, чтобы проверить, с какими аргументами она вызывалась в последний раз. Например, предположим, что у вас есть applyToAllFlavors(f) которая применяет f к набору ароматов, и вы хотите, чтобы при ее вызове последним ароматом, с которым она работает, было 'mango' . Ты можешь написать:

test('applying to all flavors does mango last', () => {
  const drink = jest.fn();
  applyToAllFlavors(drink);
  expect(drink).toHaveBeenLastCalledWith('mango');
});

.toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....)

Также под псевдонимом: .nthCalledWith(nthCall, arg1, arg2, ...)

Если у вас есть .toHaveBeenNthCalledWith функция, вы можете использовать .toHaveBeenNthCalledWith, чтобы проверить, с какими аргументами она была вызвана. Например, предположим, что у вас есть drinkEach(drink, Array<flavor>) которая применяет f к набору ароматов, и вы хотите убедиться, что при ее вызове первым ароматом, с которым она работает, будет « 'lemon' а второй — 'octopus' . Ты можешь написать:

test('drinkEach drinks each drink', () => {
  const drink = jest.fn();
  drinkEach(drink, ['lemon', 'octopus']);
  expect(drink).toHaveBeenNthCalledWith(1, 'lemon');
  expect(drink).toHaveBeenNthCalledWith(2, 'octopus');
});

note

n-й аргумент должен быть целым положительным числом,начиная с 1.

.toHaveReturned()

Также под псевдонимом: .toReturn()

Если у вас есть .toHaveReturned функция, вы можете использовать .toHaveReturned, чтобы проверить, что фиктивная функция успешно вернулась (т.е. не вызвала ошибку) хотя бы один раз. Например, предположим, что у вас есть ложный drink который возвращает true . Ты можешь написать:

test('drinks returns', () => {
  const drink = jest.fn(() => true);

  drink();

  expect(drink).toHaveReturned();
});

.toHaveReturnedTimes(number)

Также под псевдонимом: .toReturnTimes(number)

Используйте .toHaveReturnedTimes , чтобы гарантировать, что фиктивная функция успешно вернулась (т. Е. Не выдала ошибку) точное количество раз. Любые вызовы фиктивной функции, которые вызывают ошибку, не учитываются при подсчете количества возвращаемых функцией.

Например, предположим, что у вас есть drink который возвращает true . Ты можешь написать:

test('drink returns twice', () => {
  const drink = jest.fn(() => true);

  drink();
  drink();

  expect(drink).toHaveReturnedTimes(2);
});

.toHaveReturnedWith(value)

Также под псевдонимом: .toReturnWith(value)

Используйте .toHaveReturnedWith , чтобы гарантировать, что фиктивная функция вернула определенное значение.

Например, предположим, что у вас есть имитация drink которая возвращает название напитка, который был выпит. Ты можешь написать:

test('drink returns La Croix', () => {
  const beverage = {name: 'La Croix'};
  const drink = jest.fn(beverage => beverage.name);

  drink(beverage);

  expect(drink).toHaveReturnedWith('La Croix');
});

.toHaveLastReturnedWith(value)

Также под псевдонимом: .lastReturnedWith(value)

Используйте .toHaveLastReturnedWith , чтобы проверить конкретное значение, которое в последний раз вернула фиктивная функция. Если последний вызов фиктивной функции вызвал ошибку, то этот сопоставитель завершится ошибкой независимо от того, какое значение вы указали в качестве ожидаемого возвращаемого значения.

Например, предположим, что у вас есть имитация drink которая возвращает название напитка, который был выпит. Ты можешь написать:

test('drink returns La Croix (Orange) last', () => {
  const beverage1 = {name: 'La Croix (Lemon)'};
  const beverage2 = {name: 'La Croix (Orange)'};
  const drink = jest.fn(beverage => beverage.name);

  drink(beverage1);
  drink(beverage2);

  expect(drink).toHaveLastReturnedWith('La Croix (Orange)');
});

.toHaveNthReturnedWith(nthCall, value)

Также под псевдонимом: .nthReturnedWith(nthCall, value)

Используйте .toHaveNthReturnedWith , чтобы проверить конкретное значение, которое фиктивная функция вернула для n-го вызова. Если n-й вызов фиктивной функции выдал ошибку, то этот сопоставитель завершится ошибкой независимо от того, какое значение вы указали в качестве ожидаемого возвращаемого значения.

Например, предположим, что у вас есть имитация drink которая возвращает название напитка, который был выпит. Ты можешь написать:

test('drink returns expected nth calls', () => {
  const beverage1 = {name: 'La Croix (Lemon)'};
  const beverage2 = {name: 'La Croix (Orange)'};
  const drink = jest.fn(beverage => beverage.name);

  drink(beverage1);
  drink(beverage2);

  expect(drink).toHaveNthReturnedWith(1, 'La Croix (Lemon)');
  expect(drink).toHaveNthReturnedWith(2, 'La Croix (Orange)');
});

note

n-й аргумент должен быть целым положительным числом,начиная с 1.

.toHaveLength(number)

Используйте .toHaveLength , чтобы проверить, что у объекта есть свойство .length и для него установлено определенное числовое значение.

Это особенно полезно для проверки размера массивов или строк.

expect([1, 2, 3]).toHaveLength(3);
expect('abc').toHaveLength(3);
expect('').not.toHaveLength(5);

.toHaveProperty(keyPath, value?)

Используйте .toHaveProperty , чтобы проверить, существует ли свойство по keyPath ссылке keyPath для объекта. Для проверки глубоко вложенных свойств в объекте вы можете использовать точечную нотацию или массив, содержащий keyPath для глубоких ссылок.

Вы можете предоставить необязательный аргумент value для сравнения полученного значения свойства (рекурсивно для всех свойств экземпляров объекта, также известного как глубокое равенство, например сопоставление toEqual ).

В следующем примере содержится объект houseForSale с вложенными свойствами. Мы используем toHaveProperty для проверки существования и значений различных свойств в объекте.

const houseForSale = {
  bath: true,
  bedrooms: 4,
  kitchen: {
    amenities: ['oven', 'stove', 'washer'],
    area: 20,
    wallColor: 'white',
    'nice.oven': true,
  },
  livingroom: {
    amenities: [
      {
        couch: [
          ['large', {dimensions: [20, 20]}],
          ['small', {dimensions: [10, 10]}],
        ],
      },
    ],
  },
  'ceiling.height': 2,
};

test('this house has my desired features', () => {
  
  expect(houseForSale).toHaveProperty('bath');
  expect(houseForSale).toHaveProperty('bedrooms', 4);

  expect(houseForSale).not.toHaveProperty('pool');

  
  expect(houseForSale).toHaveProperty('kitchen.area', 20);
  expect(houseForSale).toHaveProperty('kitchen.amenities', [
    'oven',
    'stove',
    'washer',
  ]);

  expect(houseForSale).not.toHaveProperty('kitchen.open');

  
  expect(houseForSale).toHaveProperty(['kitchen', 'area'], 20);
  expect(houseForSale).toHaveProperty(
    ['kitchen', 'amenities'],
    ['oven', 'stove', 'washer'],
  );
  expect(houseForSale).toHaveProperty(['kitchen', 'amenities', 0], 'oven');
  expect(houseForSale).toHaveProperty(
    'livingroom.amenities[0].couch[0][1].dimensions[0]',
    20,
  );
  expect(houseForSale).toHaveProperty(['kitchen', 'nice.oven']);
  expect(houseForSale).not.toHaveProperty(['kitchen', 'open']);

  
  expect(houseForSale).toHaveProperty(['ceiling.height'], 'tall');
});

.toBeCloseTo(number, numDigits?)

Используйте toBeCloseTo для сравнения чисел с плавающей запятой для приблизительного равенства.

Необязательный аргумент numDigits ограничивает количество проверяемых цифр после десятичной точки. Для значения по умолчанию 2 критерием теста является Math.abs(expected - received) < 0.005 (то есть 10 ** -2 / 2 ).

Интуитивные сравнения равенства часто терпят неудачу,потому что арифметика десятичных (основание 10)значений часто имеет ошибки округления в двоичном представлении ограниченной точности (основание 2).Например,этот тест не работает:

test('adding works sanely with decimals', () => {
  expect(0.2 + 0.1).toBe(0.3); 
});

Это не удается, потому что в JavaScript 0.2 + 0.1 фактически 0.30000000000000004 .

Например,этот тест проходит с точностью до 5 цифр:

test('adding works sanely with decimals', () => {
  expect(0.2 + 0.1).toBeCloseTo(0.3, 5);
});

Поскольку ошибки с плавающей запятой — это проблема, toBeCloseTo решает toBeCloseTo , он не поддерживает большие целочисленные значения.

.toBeDefined()

Используйте .toBeDefined , чтобы проверить, не является ли переменная неопределенной. Например, если вы хотите проверить, что функция fetchNewFlavorIdea() что-то возвращает , вы можете написать:

test('there is a new flavor idea', () => {
  expect(fetchNewFlavorIdea()).toBeDefined();
});

Вы можете написать expect(fetchNewFlavorIdea()).not.toBe(undefined) , но лучше избегать ссылки на undefined прямо в коде.

.toBeFalsy()

Используйте .toBeFalsy , когда вам все равно, что такое значение, и вы хотите убедиться, что значение ложно в логическом контексте. Например, допустим, у вас есть код приложения, который выглядит так:

drinkSomeLaCroix();
if (!getErrors()) {
  drinkMoreLaCroix();
}

Вам может быть все равно, что возвращает getErrors , в частности — он может вернуть false , null или 0 , и ваш код все равно будет работать. Итак, если вы хотите проверить, нет ли ошибок после того, как выпили немного La Croix, вы можете написать:

test('drinking La Croix does not lead to errors', () => {
  drinkSomeLaCroix();
  expect(getErrors()).toBeFalsy();
});

В JavaScript существует шесть ложных значений: false , 0 , '' , null , undefined и NaN . Все остальное правда.

.toBeGreaterThan(number | bigint)

Используйте toBeGreaterThan для сравнения received > expected числовых или больших целочисленных значений. Например, проверьте, что ouncesPerCan() возвращает значение более 10 унций:

test('ounces per can is more than 10', () => {
  expect(ouncesPerCan()).toBeGreaterThan(10);
});

.toBeGreaterThanOrEqual(number | bigint)

Используйте toBeGreaterThanOrEqual для сравнения received >= expected числовых или больших целочисленных значений. Например, проверьте, что ouncesPerCan() возвращает значение не менее 12 унций:

test('ounces per can is at least 12', () => {
  expect(ouncesPerCan()).toBeGreaterThanOrEqual(12);
});

.toBeLessThan(number | bigint)

Используйте toBeLessThan для сравнения received < expected числовых или больших целочисленных значений. Например, проверьте, что ouncesPerCan() возвращает значение менее 20 унций:

test('ounces per can is less than 20', () => {
  expect(ouncesPerCan()).toBeLessThan(20);
});

.toBeLessThanOrEqual(number | bigint)

Используйте toBeLessThanOrEqual для сравнения received <= expected числовых или больших целочисленных значений. Например, проверьте, что ouncesPerCan() возвращает значение не более 12 унций:

test('ounces per can is at most 12', () => {
  expect(ouncesPerCan()).toBeLessThanOrEqual(12);
});

.toBeInstanceOf(Class)

Используйте .toBeInstanceOf(Class) чтобы проверить, является ли объект экземпляром класса. Этот сопоставитель использует instanceof внизу.

class A {}

expect(new A()).toBeInstanceOf(A);
expect(() => {}).toBeInstanceOf(Function);
expect(new A()).toBeInstanceOf(Function); 

.toBeNull()

.toBeNull() то же самое, что .toBe(null) но сообщения об ошибках немного приятнее. Поэтому используйте .toBeNull() если хотите проверить, что что-то имеет значение null.

function bloop() {
  return null;
}

test('bloop returns null', () => {
  expect(bloop()).toBeNull();
});

.toBeTruthy()

Используйте .toBeTruthy , если вам все равно, что такое значение, и вы хотите убедиться, что значение истинно в логическом контексте. Например, допустим, у вас есть код приложения, который выглядит так:

drinkSomeLaCroix();
if (thirstInfo()) {
  drinkMoreLaCroix();
}

Вам может быть все равно, что возвращает thirstInfo , в частности — он может вернуть true или сложный объект, и ваш код все равно будет работать. Так что если вы хотите проверить , что thirstInfo будет truthy выпив некоторое La Croix, вы могли бы написать:

test('drinking La Croix leads to having thirst info', () => {
  drinkSomeLaCroix();
  expect(thirstInfo()).toBeTruthy();
});

В JavaScript существует шесть ложных значений: false , 0 , '' , null , undefined и NaN . Все остальное правда.

.toBeUndefined()

Используйте .toBeUndefined , чтобы проверить, что переменная не определена. Например, если вы хотите проверить, что функция bestDrinkForFlavor(flavor) возвращает значение undefined для вкуса 'octopus' , потому что хорошего напитка со вкусом осьминога не существует:

test('the best drink for octopus flavor is undefined', () => {
  expect(bestDrinkForFlavor('octopus')).toBeUndefined();
});

Вы можете написать expect(bestDrinkForFlavor('octopus')).toBe(undefined) , но лучше избегать ссылки на undefined прямо в коде.

.toBeNaN()

Используйте .toBeNaN при проверке значения NaN .

test('passes when value is NaN', () => {
  expect(NaN).toBeNaN();
  expect(1).not.toBeNaN();
});

.toContain(item)

Используйте .toContain , если хотите проверить, находится ли элемент в массиве. Для тестирования элементов в массиве используется === , строгая проверка на равенство. .toContain также может проверять, является ли строка подстрокой другой строки.

Например, если getAllFlavors() возвращает массив вкусов и вы хотите быть уверены, что там есть lime , вы можете написать:

test('the flavor list contains lime', () => {
  expect(getAllFlavors()).toContain('lime');
});

Этот матчер также принимает другие итерации,такие как строки,множества,списки узлов и коллекции HTML.

.toContainEqual(item)

Используйте .toContainEqual , если вы хотите проверить, что элемент с определенной структурой и значениями содержится в массиве. Для тестирования элементов в массиве этот сопоставитель рекурсивно проверяет равенство всех полей, а не проверяет идентичность объекта.

describe('my beverage', () => {
  test('is delicious and not sour', () => {
    const myBeverage = {delicious: true, sour: false};
    expect(myBeverages()).toContainEqual(myBeverage);
  });
});

.toEqual(value)

Используйте .toEqual для рекурсивного сравнения всех свойств экземпляров объекта (также известного как «глубокое» равенство). Он вызывает Object.is для сравнения примитивных значений, что даже лучше для тестирования, чем оператор строгого равенства === .

Например, .toEqual и .toBe ведут себя по-разному в этом наборе тестов, поэтому все тесты проходят:

const can1 = {
  flavor: 'grapefruit',
  ounces: 12,
};
const can2 = {
  flavor: 'grapefruit',
  ounces: 12,
};

describe('the La Croix cans on my desk', () => {
  test('have all the same properties', () => {
    expect(can1).toEqual(can2);
  });
  test('are not the exact same can', () => {
    expect(can1).not.toBe(can2);
  });
});

tip

.toEqual не будет выполнять глубокую проверку на равенство для двух ошибок. Только свойство message объекта Error считается равным. Для проверки на наличие ошибок рекомендуется использовать сопоставитель .toThrow .

Если различия между свойствами не помогают понять, почему тест не проходит, особенно если отчет большой, то вы можете перенести сравнение в функцию expect . Например, используйте метод equals класса Buffer , чтобы проверить, содержат ли буферы одно и то же содержимое:

  • перезаписать expect(received).toEqual(expected) как ожидаемый expect(received.equals(expected)).toBe(true)
  • переписать expect(received).not.toEqual(expected) как ожидаемый expect(received.equals(expected)).toBe(false)

.toMatch(regexp | string)

Используйте .toMatch , чтобы проверить, соответствует ли строка регулярному выражению.

Например, вы можете не знать, что именно возвращает essayOnTheBestFlavor() , но знаете, что это действительно длинная строка, и где-то там должна быть подстрока grapefruit . Вы можете проверить это с помощью:

describe('an essay on the best flavor', () => {
  test('mentions grapefruit', () => {
    expect(essayOnTheBestFlavor()).toMatch(/grapefruit/);
    expect(essayOnTheBestFlavor()).toMatch(new RegExp('grapefruit'));
  });
});

Этот матчер также принимает строку,которую он попытается сопоставить:

describe('grapefruits are healthy', () => {
  test('grapefruits are a fruit', () => {
    expect('grapefruits').toMatch('fruit');
  });
});

.toMatchObject(object)

Используйте .toMatchObject , чтобы проверить, соответствует ли объект JavaScript подмножеству свойств объекта. Он сопоставляет полученные объекты со свойствами, которых нет в ожидаемом объекте.

Вы также можете передать массив объектов, и в этом случае метод вернет true, только если каждый объект в полученном массиве совпадает (в смысле toMatchObject , описанном выше) с соответствующим объектом в ожидаемом массиве. Это полезно, если вы хотите проверить совпадение двух массивов по количеству элементов, в отличие от arrayContaining , который позволяет добавлять дополнительные элементы в полученный массив.

Вы можете сравнивать свойства со значениями или с матчами.

const houseForSale = {
  bath: true,
  bedrooms: 4,
  kitchen: {
    amenities: ['oven', 'stove', 'washer'],
    area: 20,
    wallColor: 'white',
  },
};
const desiredHouse = {
  bath: true,
  kitchen: {
    amenities: ['oven', 'stove', 'washer'],
    wallColor: expect.stringMatching(/white|yellow/),
  },
};

test('the house has my desired features', () => {
  expect(houseForSale).toMatchObject(desiredHouse);
});
describe('toMatchObject applied to arrays', () => {
  test('the number of elements must match exactly', () => {
    expect([{foo: 'bar'}, {baz: 1}]).toMatchObject([{foo: 'bar'}, {baz: 1}]);
  });

  test('.toMatchObject is called for each elements, so extra object properties are okay', () => {
    expect([{foo: 'bar'}, {baz: 1, extra: 'quux'}]).toMatchObject([
      {foo: 'bar'},
      {baz: 1},
    ]);
  });
});

.toMatchSnapshot(propertyMatchers?, hint?)

Это гарантирует, что значение соответствует самому последнему снимку. Ознакомьтесь с руководством по тестированию снимков для получения дополнительной информации.

Вы можете предоставить необязательный аргумент объекта propertyMatchers , который имеет асимметричные сопоставители как значения подмножества ожидаемых свойств, если полученное значение будет экземпляром объекта . Это похоже на toMatchObject с гибкими критериями для подмножества свойств, за которым следует тест снимка в качестве точных критериев для остальных свойств.

Вы можете указать необязательный аргумент строки hint который будет добавлен к имени теста. Хотя Jest всегда добавляет число в конце имени снимки, короткие описательные подсказки могут быть более полезными , чем числа , чтобы различать несколько снимков в едином it или test блок. Jest сортирует снимки по имени в соответствующем файле .snap .

.toMatchInlineSnapshot(propertyMatchers?, inlineSnapshot)

Обеспечивает соответствие значения последнему снимку.

Вы можете предоставить необязательный аргумент объекта propertyMatchers , который имеет асимметричные сопоставители как значения подмножества ожидаемых свойств, если полученное значение будет экземпляром объекта . Это похоже на toMatchObject с гибкими критериями для подмножества свойств, за которым следует тест снимка в качестве точных критериев для остальных свойств.

Jest добавляет строковый аргумент inlineSnapshot к сопоставителю в тестовом файле (вместо внешнего файла .snap ) при первом запуске теста.

Ознакомьтесь с разделом « Встроенные снимки» для получения дополнительной информации.

.toStrictEqual(value)

Используйте .toStrictEqual , чтобы проверить, что объекты имеют одинаковые типы и структуру.

Отличия от .toEqual :

  • Проверяются ключи с undefined свойствами. например, {a: undefined, b: 2} не соответствует {b: 2} при использовании .toStrictEqual .
  • Проверяется разреженность массива. например, [, 1] не соответствует [undefined, 1] при использовании .toStrictEqual .
  • Проверяется соответствие типов объектов. например, экземпляр класса с полями a и b не будет равняться буквальному объекту с полями a и b .
class LaCroix {
  constructor(flavor) {
    this.flavor = flavor;
  }
}

describe('the La Croix cans on my desk', () => {
  test('are not semantically the same', () => {
    expect(new LaCroix('lemon')).toEqual({flavor: 'lemon'});
    expect(new LaCroix('lemon')).not.toStrictEqual({flavor: 'lemon'});
  });
});

.toThrow(error?)

Также под псевдонимом: .toThrowError(error?)

Используйте .toThrow , чтобы проверить, вызывает ли функция при ее вызове. Например, если мы хотим проверить, что drinkFlavor('octopus') бросает, потому что вкус осьминога слишком отвратителен для питья, мы могли бы написать:

test('throws on octopus', () => {
  expect(() => {
    drinkFlavor('octopus');
  }).toThrow();
});

tip

Вы должны обернуть код в функцию,иначе ошибка не будет поймана и утверждение не пройдет.

Вы можете предоставить необязательный аргумент для проверки того,что конкретная ошибка выбрасывается:

  • регулярное выражение: сообщение об ошибке соответствует шаблону
  • строка: сообщение об ошибке включает подстроку
  • объект ошибки: сообщение об ошибке равно свойству сообщения объекта
  • класс ошибки: объект ошибки является экземпляром класса

Например, предположим, что drinkFlavor имеет такой код:

function drinkFlavor(flavor) {
  if (flavor == 'octopus') {
    throw new DisgustingFlavorError('yuck, octopus flavor');
  }
  
}

Мы могли бы протестировать,что эта ошибка выбрасывается несколькими способами:

test('throws on octopus', () => {
  function drinkOctopus() {
    drinkFlavor('octopus');
  }

  
  expect(drinkOctopus).toThrowError(/yuck/);
  expect(drinkOctopus).toThrowError('yuck');

  
  expect(drinkOctopus).toThrowError(/^yuck, octopus flavor$/);
  expect(drinkOctopus).toThrowError(new Error('yuck, octopus flavor'));

  
  expect(drinkOctopus).toThrowError(DisgustingFlavorError);
});

.toThrowErrorMatchingSnapshot(hint?)

Используйте .toThrowErrorMatchingSnapshot , чтобы проверить, что функция выдает ошибку, соответствующую самому последнему снимку при ее вызове.

Вы можете указать необязательный аргумент строки hint который будет добавлен к имени теста. Хотя Jest всегда добавляет число в конце имени снимки, короткие описательные подсказки могут быть более полезными , чем числа , чтобы различать несколько снимков в едином it или test блок. Jest сортирует снимки по имени в соответствующем файле .snap .

Например, предположим, что у вас есть функция drinkFlavor , которая срабатывает всякий раз, когда аромат 'octopus' , и кодируется следующим образом:

function drinkFlavor(flavor) {
  if (flavor == 'octopus') {
    throw new DisgustingFlavorError('yuck, octopus flavor');
  }
  
}

Тест для этой функции будет выглядеть так:

test('throws on octopus', () => {
  function drinkOctopus() {
    drinkFlavor('octopus');
  }

  expect(drinkOctopus).toThrowErrorMatchingSnapshot();
});

И он сгенерирует следующий снимок:

exports[`drinking flavors throws on octopus 1`] = `"yuck, octopus flavor"`;

Ознакомьтесь с React Tree Snapshot Testing для получения дополнительной информации о тестировании моментальных снимков.

.toThrowErrorMatchingInlineSnapshot(inlineSnapshot)

Используйте .toThrowErrorMatchingInlineSnapshot , чтобы проверить, что функция выдает ошибку, соответствующую самому последнему снимку, когда она вызывается.

Jest добавляет строковый аргумент inlineSnapshot к сопоставителю в тестовом файле (вместо внешнего файла .snap ) при первом запуске теста.

Ознакомьтесь с разделом « Встроенные снимки» для получения дополнительной информации.


Jest

29.0

  • Environment Variables

    Jest устанавливает следующие переменные среды: Установите «тест», если это уже не что-то другое.

  • Манекен ES6 Класс

    Jest можно использовать для имитации классов ES6, которые импортируются в файлы, которые вы хотите протестировать.

  • Jest Community

    Сообщество вокруг Jest усердно работает над тем, чтобы сделать тестирование еще лучше.

  • Объект шутки

    Объект jest автоматически находится в области видимости в каждом тестовом файле.

Понравилась статья? Поделить с друзьями:
  • Json ошибка как исправить
  • Jest обработка ошибок
  • Json ошибка 400
  • Jeep ошибка p0610
  • Jemix xps 13a ошибка