Jest not using manual mock - jestjs

I'm using Create React App. I created a Jest test that uses a manual mock. The test renders my App component and I'm trying to mock a nested component. It's still picking up the original BarChart component.
containers/__tests__/App.js
import React from 'react';
import { shallow, mount } from 'enzyme';
const barChartPath = '../../components/d3/BarChart/BarChart';
describe('App', () => {
beforeEach(() => {
const mockBarChart = require('../../components/d3/BarChart/__mocks__/BarChart').default;
jest.mock(barChartPath, () => mockBarChart);
});
it('renders without crashing - deep', () => {
const App = require('../App').default;
mount(<App />);
});
});
I tried using
import BarChart from '../../components/d3/BarChart/BarChart';
...
beforeEach(() => {
jest.mock(BarChart)
but that didn't work either.
I'm using the require statement in the beforeEach due to the issue described in Manual mock not working in with Jest
setupTests.js
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

Related

How to test react-native methods?

I want to test Vibration module of react-native, the problem is that I get an error when I try to test it:
With this component:
import React, { useEffect } from 'react';
import { Text, Vibration } from 'react-native';
interface Props {}
export const MyComponent = (props: Props) => {
useEffect(() => Vibration.vibrate(1), []);
return (
<Text>asdaf</Text>
);
};
And this test file:
// #ts-nocheck
import React from 'react';
import { render } from '#testing-library/react-native';
import { NativeModules } from 'react-native';
import { MyComponent } from '../../../src/modules/MyComponent';
describe('MyComponent', () => {
it('alpha', () => {
const { debug } = render(<MyComponent/>);
expect(true).toBeTruthy();
});
});
I get this error:
Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'Vibration' could not be found. Verify that a module by this name is registered in the native binary.
I tried to mock react-native like this:
// #ts-nocheck
import React from 'react';
import { render } from '#testing-library/react-native';
import { NativeModules } from 'react-native';
import { ChatRoomContainer } from '../../../src/modules/ChatRoom';
// Mock NativeModules
jest.mock('react-native', () => ({
...jest.requireActual('react-native'),
Vibration: {
vibrate: jest.fn()
},
__esModule: true
}));
describe('MyComponent', () => {
it('alpha', () => {
const { debug } = render(<ChatRoomContainer/>);
expect(true).toBeTruthy();
});
});
But then I get a ton of warnings related to old modules that should no longer be used:
Warning: CheckBox has been extracted from react-native core and will be removed in a future release. It can now be installed and imported from '#react-native-community/checkbox' instead of 'react-native'. See https://github.com/react-native-community/react-native-checkbox
Warning: DatePickerIOS has been merged with DatePickerAndroid and will be removed in a future release. It can now be installed and imported from '#react-native-community/datetimepicker' instead of 'react-native'. See https://github.com/react-native-community/datetimepicker
What is the best way to test such functionality (like Vibration) of react-native then?
Thanks in advance for you time!
You can mock react-native using the library path, like this:
const mockedVibrate = jest.fn();
jest.mock('react-native/Libraries/Vibration/Vibration', () => ({
vibrate: mockedVibrate,
}));

How to test a function in React Component with Jest + Enzyme?

I am using the testing-library/jest-dom + Enzyme to do the unit testing.and here I need to test a funtion inside a React function.
import React, { useEffect } from 'react';
function Component1() {
useEffect( async () => {
fetchSomeData();
}, [])
const fetchSomeData = async () =>{
console.log('fetchSomeData')
}
return <div>Component1</div>;
}
export default Component1;
and my test file:
Enzyme.configure({adapter:new Adapter()})
describe('Name of the group', () => {
it('should ', () => {
const wrapper = shallow( <Component1/>)
expect(wrapper.exists());
});
});
in fact I don't need to test the correctness , I just need the code be covered in jest. but whatever I tried , it seems not covered by jest:

jest.mock(..) not working in 'describe' (TypeError: moduleName.split is not a function)

jest.mock(..) does not seem to work at the 'describe' level for my tests.
If I have the following :
import React from 'react';
import {someFunction} from "./something/someFile";
describe('Overview Test', () => {
jest.mock(someFunction);
test(' snapshot', () => {
});
});
Then running the 'test' (ie. at the test level), works fine.
But if I run the 'describe' (ie. the describe level or suite level), then I get the following error :
TypeError: moduleName.split is not a function
at Resolver.resolveModuleFromDirIfExists (A:\frontend\node_modules\jest-resolve\build\index.js:224:30)
at Resolver.resolveModule (A:\frontend\node_modules\jest-resolve\build\index.js:252:12)
If I have this :
describe('Overview Test', () => {
test(' snapshot', () => {
jest.mock(someFunction);
});
});
Then both ways it does not work.
I have also tried this :
import React from 'react';
import {someFunction} from "./something/someFile";
describe('Overview Test', () => {
beforeEach(() => {
jest.mock(someFunction);
});
test(' snapshot', () => {
});
});
And it does not work.
UPDATE
I have also tried this and it does not work :
import React from 'react';
import {someFunction} from "./something/someFile";
describe('Overview Test', () => {
jest.mock('./something/someFile', () => {
return { someFunction: jest.fn(() => "futhissit")};
});
test(' snapshot', () => {
someFunction()
});
});
Jest mock is for mocking modules and the first argument is the moduleName which it has to be a valid module name (inside node_modules or a file path) and not a direct function/module:
jest.mock(moduleName, factory, options)
Mocks a module with an auto-mocked version when it is being required. factory and options are optional.
The error you're getting TypeError: moduleName.split is not a function is because resolveModuleFromDirIfExists tries to split the module name/path and you can see it inside jest-resolve/src/index.ts at line 207.
When you want to test an ES module, you pass the module location for the moduleName and you create a factory using __esModule: true and then create properties with exported functions being mocked using jest.fn():
someFile.js exports the someFunction:
module.exports.someFunction = () => 'Some function result!';
Mocking someFile.js module using jest.mock()
describe('Overview Test', () => {
// Mock the module and its functions
jest.mock('./someFile', () => ({
__esModule: true,
someFunction: jest.fn(() => 'Mocked someFunction!')
}));
// Import the function from the mocked module
const { someFunction } = require('./someFile');
test('snapshot', () => {
// Execute the mocked function
const someResult = someFunction();
// Expect to return the mocked value
expect(someResult).toBe('Mocked someFunction!');
});
});
You have to import the mocked modules after the jest.mock module mocking. You can create a jest.setup.js and configure it using setupFilesAfterEnv that can have your mocks inside it and then just import the modules like normal at the top of the test files.

Jest: How to test a component that dispatch an API action

I am new to testing,
I am trying to understand if it's possible to test an API call that dispatch from the component.
Is it possible to wait for a response from the server?
import React from 'react';
import { render, fireEvent, cleanup, waitForElement } from 'react-testing-library';
import 'jest-dom/extend-expect'
import App from 'src/app';
import { store } from 'stories/index.stories.js';
import { Provider, connect } from 'react-redux';
const renderComponent = () => (<App />);
it('renders correctly', () => {
const { container, getByText, queryAllByText, getByPlaceholderText } = renderComponent();
expect(container).not.toBeEmpty();
expect(getByText(/Discover/i)).toBeTruthy();
const discoverBtn = getByText(/Discover/i);
fireEvent.click(discoverBtn); // this will dispatch an action from the component
//what should i do next ?
});
This is how I do it.
First I put all my fetch requests in a separate file, say /api/index.js. In this way I can easily mock them in my tests.
Then I perform the actions that a user would do. Finally I check that the API got called and that the DOM was updated correctly.
import { aFetchMethod } from './api'
// With jest.mock our API method does nothing
// we don't want to hit the server in our tests
jest.mock('./api')
it('renders correctly', async () => {
const { getByText } = render(<App />)
aFetchMethod.mockResolvedValueOnce('some data that makes sense for you')
fireEvent.click(getByText('Discover'))
expect(aFetchMethod).toHaveBeenCalledTimes(1)
expect(aFetchMethod).toHaveBeenCalledWith('whatever you call it with')
// Let's assume you now render the returned data
await wait(() => getByText('some data that makes sense for you'))
})

How to test a module in NestJs

I'm adding tests on a project and improving coverage. I would like to know how can I test a module definition (mymodule.module.ts file) in NestJs.
In particular, I'm testing a main module that imports other modules, one of them inits a db connection, this means that I need to mock the service on the other module, to avoid a real db connection.
At this moment I have something like this:
beforeEach(async () => {
const instance: express.Application = express();
module = await NestFactory.create(MyModule, instance);
});
describe('module bootstrap', () => {
it('should initialize entities successfully', async () => {
controller = module.get(MyController);
...
expect(controller instanceof MyController).toBeTruthy();
});
});
This works, but I'm sure this can get improvements :)
The ideal thing would be something like overrideComponent method provided by Test.createTestingModule.
P.S: I'm using 4.5.2 version
Improved my tests based on #laurent-thiebault answer:
import { Test } from '#nestjs/testing';
import { ThingsModule } from './things.module';
import { ThingsResolver } from './things.resolver';
import { ThingsService } from './things.service';
describe('ThingsModule', () => {
it('should compile the module', async () => {
const module = await Test.createTestingModule({
imports: [ThingsModule],
}).compile();
expect(module).toBeDefined();
expect(module.get(ThingsResolver)).toBeInstanceOf(ThingsResolver);
expect(module.get(ThingsService)).toBeInstanceOf(ThingsService);
});
});
You can now test your module (at least for code coverage) by building it that way:
describe('MyController', () => {
let myController: MyController;
beforeEach(async () => {
const module = await Test.createTestingModule({
imports: [MyModule],
}).compile();
myController = module.get<MyController>(MyController);
});
it('should the correct value', () => {
expect(myController.<...>).toEqual(<...>);
});
});
We usually didn't test .module.ts files directly.
we do this in e2e testing.
but I wonder why one should test the the module ! and you are trying to test if the module can initialize it's components , it should.
but i recommend you do this in e2e testing.
in my opinion, in unit testing you should focus on testing the services or other components behaviors not the modules.

Resources