admin管理员组

文章数量:1134575

I'm using create-react-app and trying to write a jest test that checks the output of a console.log.

My function to test is:

export const log = logMsg => console.log(logMsg);

My test is :

it('console.log the text "hello"', () => {
  console.log = jest.fn('hello');
  expect(logMsg).toBe('hello');
});

Here is my error

 FAIL  src/utils/general.test.js
  ● console.log the text hello

    expect(received).toBe(expected)    Expected value to be (using ===):      "hello"
    Received:
      undefined
    Difference:
      Comparing two different types of values. Expected string but received undefined.

I'm using create-react-app and trying to write a jest test that checks the output of a console.log.

My function to test is:

export const log = logMsg => console.log(logMsg);

My test is :

it('console.log the text "hello"', () => {
  console.log = jest.fn('hello');
  expect(logMsg).toBe('hello');
});

Here is my error

 FAIL  src/utils/general.test.js
  ● console.log the text hello

    expect(received).toBe(expected)    Expected value to be (using ===):      "hello"
    Received:
      undefined
    Difference:
      Comparing two different types of values. Expected string but received undefined.
Share Improve this question edited Jul 12, 2020 at 18:22 norbitrial 15.1k10 gold badges38 silver badges64 bronze badges asked Mar 4, 2018 at 13:45 Hello-WorldHello-World 9,54524 gold badges90 silver badges157 bronze badges 4
  • Where is the invocation of your function inside the test? You should invoke it before you do the assertion. – JeB Commented Mar 4, 2018 at 13:48
  • Sorry but I don't understand what you mean? – Hello-World Commented Mar 4, 2018 at 13:49
  • Could you include the whole test file please? Where did you declare logMsg ? – ltamajs Commented Mar 4, 2018 at 13:53
  • Thats all I have, logMsg is meant to be the text passed in. – Hello-World Commented Mar 4, 2018 at 13:58
Add a comment  | 

5 Answers 5

Reset to default 149

If you want to check that console.log received the right parameter (the one that you passed in) you should check mock of your jest.fn().
You also have to invoke your log function, otherwise console.log is never invoked:

it('console.log the text "hello"', () => {
  console.log = jest.fn();
  log('hello');
  // The first argument of the first call to the function was 'hello'
  expect(console.log.mock.calls[0][0]).toBe('hello');
});

or

it('console.log the text "hello"', () => {
  console.log = jest.fn();
  log('hello');
  // The first argument of the first call to the function was 'hello'
  expect(console.log).toHaveBeenCalledWith('hello');
});

If you're going with this approach don't forget to restore the original value of console.log.

Another option is to use jest.spyOn (instead of replacing the console.log it will create a proxy to it):

it('console.log the text "hello"', () => {
  const logSpy = jest.spyOn(console, 'log');

  console.log('hello');

  expect(logSpy).toHaveBeenCalledWith('hello');
});

Read more here.

Or you could do it like this:

it('calls console.log with "hello"', () => {
  const consoleSpy = jest.spyOn(console, 'log');

  console.log('hello');

  expect(consoleSpy).toHaveBeenCalledWith('hello');
});

Another option is to save off a reference to the original log, replace with a jest mock for each test, and restore after all the tests have finished. This has a slight benefit to not polluting the test output and still being able to use the original log method for debugging purposes.

describe("Some behavior that will log", () => {
  const log = console.log; // save original console.log function
  beforeEach(() => {
    console.log = jest.fn(); // create a new mock function for each test
  });
  afterAll(() => {
    console.log = log; // restore original console.log after all tests
  });
  test("no log", () => {
    // TODO: test something that should not log
    expect(console.log).not.toHaveBeenCalled();
  });
  test("some log", () => {
    // TODO: execute something that should log
    expect(console.log).toHaveBeenCalledWith(
      expect.stringContaining("something")
    );
    const message = console.log.mock.calls[0][0]; // get actual log message
    log(message); // actually log out what the mock was called with
  });
});

I would consider toHaveBeenCalledWith or any other of the methods that jest offers for checking mock calls (the ones that start with toHaveBeenCalled).

it('console.log the text "hello"', () => {
  console.log = jest.fn();
  log('hello');
  expect(console.log).toHaveBeenCalledWith('hello');
});

If you call console.log with multiple parameters like `console.log('hi', ob1, obj2);

but only want to test the string:

const logSpy = jest.spyOn(console, 'log');
 const wasCalledWithTokenError = logSpy.mock.calls.some(call =>
  call.some(arg => typeof arg === 'string' && arg.includes('invalid csrf token'))
);
expect(wasCalledWithTokenError).toBeTruthy();

本文标签: javascriptHow do I test a jest consolelogStack Overflow