Reputation: 1122
The problem I am having is that the mocked constant does not change in the component after jest.doMock
.
Take a look at the minimal repo.
I have tried with mock
instead of doMock
- same error.
App.test.js
import React from "react"
import App from './App'
import '@testing-library/jest-dom'
import { render } from "@testing-library/react";
describe('testing app.js', () => {
// To reset manually mocked values
beforeEach(() => {
jest.resetModules()
});
test("SET CONSTANT TO 1", () => {
jest.doMock('./myConstants.js', () => ({
CONSTANT: {
NUMBER: 1
}
}))
const { getByText, getByLabelText } = render(<App />)
expect(getByText('1')).toBeInTheDocument()
})
test("SET CONSTANT TO 3", () => {
jest.doMock('./myConstants.js', () => ({
CONSTANT: {
NUMBER: 3
}
}))
const { getByText, getByLabelText } = render(<App />)
expect(getByText('3')).toBeInTheDocument()
})
})
App.js
import React from "react"
import { CONSTANT } from './myConstants.js'
console.log(CONSTANT)
const App = () => {
return (
<div>
{CONSTANT.NUMBER}
</div>
);
}
export default App;
myConstants.js:
export const CONSTANT = { NUMBER: 2 }
Both of the tests above fail. The output from one of them is:
TestingLibraryElementError: Unable to find an element with the text: 3. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
<body>
<div>
<div>
2
</div>
</div>
</body>
29 | }))
30 | const { getByText, getByLabelText } = render(<App />)
> 31 | expect(getByText('3')).toBeInTheDocument()
Although the provided solution worked perfectly, I did not want to rewrite each component I was going to test (by adding require(...)
). A workaround was to use import("./App").then((module)
import React from "react"
import App from './App'
import '@testing-library/jest-dom'
import { render } from "@testing-library/react";
describe('testing app.js', () => {
// To reset manually mocked values
beforeEach(() => {
jest.resetModules()
});
jest.doMock('./myConstants.js', () => {
return {
__esModule: true,
CONSTANT: {
NUMBER: 1
}
}
})
test("SET CONSTANT TO 1", () => {
// Wait for mock done
return import('./myConstants.js').then((constants) => {
console.log(constants.CONSTANT.NUMBER)
expect(constants.CONSTANT.NUMBER).toBe(1)
import("./App").then((module) => {
const { getByText, getByLabelText } = render(<module.default />)
expect(getByText('1')).toBeInTheDocument()
})
})
})
})
Upvotes: 6
Views: 12095
Reputation: 17514
I'm guessing we could also mutate the mocked value directly by still using jest.mock
as following:
import React from "react"
import App from './App'
import '@testing-library/jest-dom'
import { render } from "@testing-library/react";
import { CONSTANT} from "./myConstants";
jest.mock('./myConstants.js', () => ({
CONSTANT: {
NUMBER: 0,
}
}))
describe('testing app.js', () => {
// To reset manually mocked values
beforeEach(() => {
jest.resetModules()
});
test("SET CONSTANT TO 1", () => {
// Mutate directly mocked value by setting our desired value
CONSTANT.NUMBER = 1;
const { getByText, getByLabelText } = render(<App />)
expect(getByText('1')).toBeInTheDocument()
})
test("SET CONSTANT TO 3", () => {
// Likewise we set it as 3
CONSTANT.NUMBER = 3;
const { getByText, getByLabelText } = render(<App />)
expect(getByText('4')).toBeInTheDocument()
})
})
Upvotes: 3
Reputation: 17514
Using jest.doMock
is quite complicated than you thought. Basically it requires you do a few steps as described https://jestjs.io/docs/en/jest-object#jestdomockmodulename-factory-options.
Which means you have to change your test to meet above requirements as:
test("SET CONSTANT TO 1", () => {
jest.doMock('./myConstants.js', () => {
return {
__esModule: true,
CONSTANT: {
NUMBER: 1
}
}
})
// Wait for mock done
return import('./myConstants.js').then(() => {
const { getByText, getByLabelText } = render(<App />)
expect(getByText('1')).toBeInTheDocument()
})
})
// While you also require your code right before using instead of `require` at the top level:
const App = () => {
// Require to use it right before using it
const { CONSTANT } = require('./myConstants.js');
return (
<div>
{CONSTANT.NUMBER}
</div>
);
}
Upvotes: 4