admin管理员组

文章数量:1391999

Given the following example with a basic test, I'd expect bar to be returned when sendMessage.message is mocked with Jest. Instead, when called, it returns the original value of "Hello World".

serviceBus.js

export const message = () => {
  return "Hello world";
};

export const foo = () => {
  return message();
};

mockDemo.test.js

import * as sendMessage from "../src/services/serviceBus";

describe("sendMessage", () => {
  sendMessage.message = jest.fn(() => {
    return "bar";
  });

  it(`message should return bar`, async () => {
    expect(sendMessage.message()).toBe("bar");
    expect(sendMessage.foo()).toBe("bar");
  });
});

And the results as follows:

$ ./node_modules/.bin/jest ./__tests__/mockDemo.test.js
 FAIL  __tests__/mockDemo.test.js
  MessageReceiver Router
    ✕ message should return bar (9ms)

  ● MessageReceiver Router › message should return bar

    expect(received).toBe(expected) // Object.is equality

    Expected: "bar"
    Received: "Hello world"

       9 |   it(`message should return bar`, async () => {
      10 |     expect(sendMessage.message()).toBe("bar");
    > 11 |     expect(sendMessage.foo()).toBe("bar");
         |                               ^
      12 |   });
      13 | });
      14 |

      at Object.<anonymous> (__tests__/mockDemo.test.js:11:31)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total

It looks as if sendMessage.foo is calling the bound function once imported of message, which by default returns Hello World.

How would one mock message in this context?

Update

Using jest.fn().mockImplementation(() => "bar"); results in the same behaviour:

describe("MessageReceiver Router", () => {
  //   sendMessage.message.mockImplementation = jest.fn(() => {
  //     return "bar";
  //   });

  sendMessage.message = jest.fn().mockImplementation(() => "bar");

  it(`message should return bar`, async () => {
    expect(sendMessage.message()).toBe("bar");
    expect(sendMessage.foo()).toBe("bar");
  });
});

Results:

$ ./node_modules/.bin/jest ./__tests__/mockDemo.test.js
 FAIL  __tests__/mockDemo.test.js
  MessageReceiver Router
    ✕ message should return bar (10ms)

  ● MessageReceiver Router › message should return bar

    expect(received).toBe(expected) // Object.is equality

    Expected: "bar"
    Received: "Hello world"

      11 |   it(`message should return bar`, async () => {
      12 |     expect(sendMessage.message()).toBe("bar");
    > 13 |     expect(sendMessage.foo()).toBe("bar");
         |                               ^
      14 |   });
      15 | });
      16 |

      at Object.<anonymous> (__tests__/mockDemo.test.js:13:31)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        2.175s

Given the following example with a basic test, I'd expect bar to be returned when sendMessage.message is mocked with Jest. Instead, when called, it returns the original value of "Hello World".

serviceBus.js

export const message = () => {
  return "Hello world";
};

export const foo = () => {
  return message();
};

mockDemo.test.js

import * as sendMessage from "../src/services/serviceBus";

describe("sendMessage", () => {
  sendMessage.message = jest.fn(() => {
    return "bar";
  });

  it(`message should return bar`, async () => {
    expect(sendMessage.message()).toBe("bar");
    expect(sendMessage.foo()).toBe("bar");
  });
});

And the results as follows:

$ ./node_modules/.bin/jest ./__tests__/mockDemo.test.js
 FAIL  __tests__/mockDemo.test.js
  MessageReceiver Router
    ✕ message should return bar (9ms)

  ● MessageReceiver Router › message should return bar

    expect(received).toBe(expected) // Object.is equality

    Expected: "bar"
    Received: "Hello world"

       9 |   it(`message should return bar`, async () => {
      10 |     expect(sendMessage.message()).toBe("bar");
    > 11 |     expect(sendMessage.foo()).toBe("bar");
         |                               ^
      12 |   });
      13 | });
      14 |

      at Object.<anonymous> (__tests__/mockDemo.test.js:11:31)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total

It looks as if sendMessage.foo is calling the bound function once imported of message, which by default returns Hello World.

How would one mock message in this context?

Update

Using jest.fn().mockImplementation(() => "bar"); results in the same behaviour:

describe("MessageReceiver Router", () => {
  //   sendMessage.message.mockImplementation = jest.fn(() => {
  //     return "bar";
  //   });

  sendMessage.message = jest.fn().mockImplementation(() => "bar");

  it(`message should return bar`, async () => {
    expect(sendMessage.message()).toBe("bar");
    expect(sendMessage.foo()).toBe("bar");
  });
});

Results:

$ ./node_modules/.bin/jest ./__tests__/mockDemo.test.js
 FAIL  __tests__/mockDemo.test.js
  MessageReceiver Router
    ✕ message should return bar (10ms)

  ● MessageReceiver Router › message should return bar

    expect(received).toBe(expected) // Object.is equality

    Expected: "bar"
    Received: "Hello world"

      11 |   it(`message should return bar`, async () => {
      12 |     expect(sendMessage.message()).toBe("bar");
    > 13 |     expect(sendMessage.foo()).toBe("bar");
         |                               ^
      14 |   });
      15 | });
      16 |

      at Object.<anonymous> (__tests__/mockDemo.test.js:13:31)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        2.175s
Share Improve this question edited Feb 18, 2020 at 16:01 steadweb asked Feb 18, 2020 at 15:56 steadwebsteadweb 16.7k3 gold badges38 silver badges53 bronze badges 3
  • sendMessage.message.mockImplementation? – evolutionxbox Commented Feb 18, 2020 at 15:56
  • Doesn't work unfortunately :/ – steadweb Commented Feb 18, 2020 at 15:58
  • Ah. It has been closed over. So you may not be able to. – evolutionxbox Commented Feb 18, 2020 at 15:59
Add a ment  | 

2 Answers 2

Reset to default 3

So internal functions called cannot be mocked or spyed on. To fix this, you need to create an object of services, and export that instead.

serviceBus.js

const message = () => {
  return "Hello world";
};

const foo = () => {
  return services.message();
};

const services = {
  message,
  foo
};

export default services;

mockDemo.test.js

import sendMessage from "../src/services/serviceBus";

describe("MessageReceiver Router", () => {
  sendMessage.message = jest.fn(() => {
    return "bar";
  });

  it(`message should return bar`, async () => {
    expect(sendMessage.message()).toBe("bar");
    expect(sendMessage.foo()).toBe("bar");
  });
});

You should use spyOn method to mock the sendMessage.message method.

import * as sendMessage from "../src/services/serviceBus";

describe("sendMessage", () => {
   jest.spyOn(sendMessage, 'message').mockReturnValue("bar")

  it(`message should return bar`, async () => {
    expect(sendMessage.message()).toBe("bar");
    expect(sendMessage.foo()).toBe("bar");
  });
});

本文标签: javascriptMock exported const arrow functions with JestStack Overflow