How to Use toHaveBeenCalledWith in Jest
By Yogendra Porwal, Community Contributor - December 24, 2024
Jest is a popular testing framework for JavaScript, widely used for validating applications and ensuring code quality. One of Jest’s valuable features is its ability to verify how functions are called, including the arguments they receive.
This is where toHaveBeenCalledWith comes in handy. It’s a matcher in Jest that allows us to check if a mock function was called with specific arguments, making it essential for effective and precise test validations.
This guide explores what toHaveBeenCalledWith is in Jest, how to use it, and why it’s important for robust testing.
- What is toHaveBeenCalledWith?
- The Importance of toHaveBeenCalledWith in Jest
- Syntax and Examples of toHaveBeenCalledWith
What is toHaveBeenCalledWith?
In Jest, toHaveBeenCalledWith is a matcher used to assert that a mock function has been called with particular arguments.
When you write tests, sometimes you need to confirm not only that a function was called, but also that it was called with the expected data.
For example, in scenarios where you have functions dependent on specific parameters to function correctly, jest toHaveBeenCalledWith allows to validate this setup.
This matcher enhances test reliability by providing detailed verification. By using toHaveBeenCalledWith, you can verify if a function received the right arguments, ensuring it behaves as expected.
Also Read: Understanding Testing Library Jest DOM
The Importance of toHaveBeenCalledWith in Jest
Checking arguments passed to functions is important for testing complex logic and behavior. toHaveBeenCalledWith is particularly useful when working with mocked functions that represent dependencies in code tested independently of external factors.
By validating the exact arguments passed to a function, this matcher lets developers write accurate and reliable tests, reducing the chances of bugs due to incorrect parameters.
Read More: How to find Bugs in Software?
Syntax and Examples of toHaveBeenCalledWith
Using toHaveBeenCalledWith is straightforward.
Here’s the basic syntax:
javascript expect(mockFunction).toHaveBeenCalledWith(arg1, arg2, ...);
Example
Suppose you have a function, sendGreeting, that calls another function, sendGreeting, with a message:
javascript function greet(name) { sendGreeting(`Hello, ${name}!`); }
Here, the intention is to test if sendGreeting is called with the correct message.
This is how you can use toHaveBeenCalledWith:
javascript test('calls sendGreeting with the correct message', () => { const sendGreeting = jest.fn(); greet('Alice'); expect(sendGreeting).toHaveBeenCalledWith('Hello, Alice!'); });
This test checks if sendGreeting was called with “Hello, Alice!”. If it was called with different arguments, Jest would fail the test, clearly indicating what went wrong.
Here, jest.fn(), is used to create a mock function for sendGreeting. This functionality of mocking a function of jest, enables you to call a function without actually implementing it and spy on the behavior of the called function.
Read More: it.each function in Jest
How to Use toHaveBeenCalledWith
Here is a step-by-step process to use to toHaveBeenCalledWith
Prerequisites
Below are the requirements to use toHaveBeenCalledWith with jest:
- Node.js should be installed.
- VS Code should be installed.
- Previous experience with Jest would be beneficial.
- A basic understanding of React JS is expected.
- Sample React JS App and Jest test for reference
Steps to Implement toHaveBeenCalledWith
Scenario: Here is a React component called GreetingButton. When clicked, the button triggers a greet function. The test will validate whether the greet function is called with the correct argument when the button is clicked.
1. Set Up the Component
Create a simple component in GreetingButton.js to be tested:
import React from 'react'; const GreetingButton = ({ greet }) => { return ( <button onClick={() => greet('Hello, User!')}> Click to Greet </button> ); }; export default GreetingButton;
2. Write the Jest Test with toHaveBeenCalledWith
To test this component, the greet function will be mocked and verified to see if it’s called with the correct argument when the button is clicked.
In GreetingButton.test.js, write the following test:
import React from 'react'; import { render, fireEvent } from '@testing-library/react'; import GreetingButton from './GreetingButton'; test('calls greet with "Hello, User!" when button is clicked', () => { // Step 1: Create a mock function for greet const greetMock = jest.fn(); // Step 2: Render the component with the mock function passed as prop const { getByText } = render(<GreetingButton greet={greetMock} />); // Step 3: Simulate a button click fireEvent.click(getByText('Click to Greet')); // Step 4: Use toHaveBeenCalledWith to verify the argument expect(greetMock).toHaveBeenCalledWith('Hello, User!'); });
Explanation of Each Step
- Step 1: We create a mock function using jest.fn() to simulate the greet function.
- Step 2: We render the GreetingButton component and pass the mock function as a prop.
- Step 3: We use fireEvent.click to simulate a click event on the button.
- Step 4: Finally, expect(greetMock).toHaveBeenCalledWith(‘Hello, User!’) verifies that greet was called with the exact argument.
This approach helps ensure the component’s function behaves as expected.
By following these steps, you can confidently validate function calls with exact arguments, adding precision to your tests.
After Adding these files, your project should look like this:
Note: Please ignore the extra files; those are part of the sample react app.
3. Run this component Test with the below command.
npx jest GreetingButton.test.js
The console output shown below should be displayed if the test is passed.
The whole code is also available in the Github Repository for reference.
Common Challenges of Using toHaveBeenCalledWith
Using toHaveBeenCalledWith is generally straightforward, but there are some common challenges, such as:
- Partial Argument Matching: Ensuring only certain properties in a complex object were passed while ignoring others.
These can be done by using objectContaining() alongside toHaveBeenCalledWith expect(mockFunction).toHaveBeenCalledWith(expect.objectContaining({ key: 'value' }));
- Array Argument Matching: Matching specific elements in arrays when not all elements need verification.
These can be achieved using arrayContaining() alongside toHaveBeenCalledWith expect(mockFunction).toHaveBeenCalledWith(expect.arrayContaining([‘Some Text’]));
- Handling Undefined or Null Values: Ensuring tests accurately handle cases where arguments might be null or undefined.
- Deeply Nested Objects: Comparing complex, deeply nested structures can sometimes lead to mismatches if object references differ.
Integrating BrowserStack Automate with Jest Test Suite
For those aiming to execute automated tests on real browsers and devices, integrating BrowserStack with Jest is highly beneficial.
BrowserStack Automate enables running Jest tests on various environments, ensuring comprehensive cross-browser compatibility. By setting up BrowserStack in your Jest suite, you can test across platforms seamlessly.
If you are using Jest with Selenium, then you can easily run them on the BrowserStack Automate platform using the steps below.
1. Sign up for BrowserStack
2. Select ‘Accounts & Profile’
3. Select ‘Overview’ under ‘Accounts & Profile’
4. Under ‘Overview’, Click ‘My Profile’ on the left-side panel
5. Note down your Username and Access Key
6. Run the below command to install BrowserStack NodeJS SDK and set up your username and access key.
npm i -D browserstack-node-sdk@latest npx setup --username "<your-username>" --key "<your-access-key>"
7. The command will create browserstack.yml, containing all the configurations required to run the test on BrowserStack. You can refer to the configuration page to customize the parameter and copy it to browserstack.yml.
Sample browserstack.yml. # ============================= # Set BrowserStack Credentials # ============================= userName: farjigamer_mHZ0IY accessKey: c8zy5Cyz8dnykShCSj6c # ====================== # BrowserStack Reporting # ====================== projectName: BrowserStack Samples buildName: browserstack build buildIdentifier: '#${BUILD_NUMBER}' # Supports strings along with either/both ${expression} # ======================================= # Platforms (Browsers / Devices to test) # ======================================= platforms: - os: OS X osVersion: Big Sur browserName: Chrome browserVersion: latest - os: Windows osVersion: 10 browserName: Edge browserVersion: latest # ======================= # Parallels per Platform # ======================= parallelsPerPlatform: 1 # ========================================== # BrowserStack Local # (For localhost, staging/private websites) # ========================================== browserstackLocal: true # <boolean> (Default false) # =================== # Debugging features # =================== debug: false # <boolean> # Set to true if you need screenshots for every selenium command ran networkLogs: false # <boolean> Set to true to enable HAR logs capturing consoleLogs: errors # <string> Remote browser's console debug levels to be printed (Default: errors) testObservability: true
8. Run the command below to start the execution of the tests.
browserstack-node-sdk jest
To integrate BrowserStack with Jest, follow the documentation available here. This will guide you through configuring your tests to run on BrowserStack’s infrastructure, enhancing test coverage.
Best Practices for Effectively Using toHaveBeenCalledWith
- Use Mock Functions Wisely: Mock functions should represent realistic dependencies.
- Avoid Overly Specific Assertions: Match only essential parts of objects to avoid breaking tests with minor changes.
- Combine with Other Matchers: Use toHaveBeenCalledTimes alongside toHaveBeenCalledWith for precise control over function calls.
- Keep Tests Readable: Avoid overly complex mocks; keep tests easy to understand and maintain.
Conclusion
toHaveBeenCalledWith is a powerful tool in Jest for verifying function arguments, providing valuable insights into code behavior. By using it effectively, you can improve test precision and reliability. Combine it with BrowserStack for full cross-platform and cross-browser testing, ensuring your code performs as expected across diverse environments.
Frequently Asked Questions
1. How do I use “toHaveBeenCalledWith” and only match part of an object in an array argument?
To match a specific part of an object in an array argument, you can use Jest’s expect.arrayContaining and expect.objectContaining with toHaveBeenCalledWith . This is handy when a function is called with complex objects, and you only need to verify specific properties.
2. How to use toHaveBeenCalledWith to check a specific parameter?
To verify a specific parameter among multiple arguments, you can use Jest’s expect.any or null/undefined placeholders for the other parameters you’re not interested in. This ensures that your test is concise and focused on verifying the parameter you care about without needing to validate the entire function call.
Useful Resources for Jest
Understanding Jest
- Jest Framework Tutorial: How to use it?
- Unit Testing of React Apps using JEST : Tutorial
- Understanding Jest-Globals
- Understanding Jest beforeEach Function
- Understanding Testing Library Jest DOM
- Understanding Jest Mock Hook
- it.each function in Jest
Use Cases
- How to Debug Jest Tests?
- How to Run Jest Tests for a Specific File/Folder
- How to Configure Jest
- How to test React App using Jest
- How to write Snapshot Tests for React Components with Jest?
- Performing NodeJS Unit testing using Jest
- Snapshot Testing with Jest
Framework Comparisons