---id: mockingtitle: Mocking---When writing tests it's only a matter of time before you need to create a "fake" version of an internal — or external — service. This is commonly referred to as mocking. WebdriverIO provides utility functions to help you out. You can `import { fn, spyOn, mock, unmock } from '@wdio/browser-runner'` to access it. See more information about the available mocking utilities in the [API docs](/docs/api/modules#wdiobrowser-runner).## FunctionsIn order to validate whether certain function handler are called as part of your component tests, the `@wdio/browser-runner` module exports mocking primitives you can use to test, if these functions have been called. You can import these methods via:```jsimport { fn, spyOn } from '@wdio/browser-runner'```By importing `fn` you can create a spy function (mock) to track its execution and with `spyOn` track a method on an already created object.<TabsdefaultValue="mocks"values={[{label: 'Mocks', value: 'mocks'},{label: 'Spies', value: 'spies'}]}><TabItem value="mocks">The full example can be found in the [Component Testing Example](https://github.com/webdriverio/component-testing-examples/blob/main/react-typescript-vite/src/tests/LoginForm.test.tsx) repository.```tsimport React from 'react'import { $, expect } from '@wdio/globals'import { fn } from '@wdio/browser-runner'import { Key } from 'webdriverio'import { render } from '@testing-library/react'import LoginForm from '../components/LoginForm'describe('LoginForm', () => {it('should call onLogin handler if username and password was provided', async () => {const onLogin = fn()render(<LoginForm onLogin={onLogin} />)await $('input[name="username"]').setValue('testuser123')await $('input[name="password"]').setValue('s3cret')await browser.keys(Key.Enter)/*** verify the handler was called*/expect(onLogin).toBeCalledTimes(1)expect(onLogin).toBeCalledWith(expect.equal({username: 'testuser123',password: 's3cret'}))})})```</TabItem><TabItem value="spies">The full example can be found in the [examples](https://github.com/webdriverio/webdriverio/blob/main/examples/wdio/browser-runner/lit.test.js) directory.```jsimport { expect, $ } from '@wdio/globals'import { spyOn } from '@wdio/browser-runner'import { html, render } from 'lit'import { SimpleGreeting } from './components/LitComponent.ts'const getQuestionFn = spyOn(SimpleGreeting.prototype, 'getQuestion')describe('Lit Component testing', () => {it('should render component', async () => {render(html`<simple-greeting name="WebdriverIO" />`,document.body)const innerElem = await $('simple-greeting').$('p')expect(await innerElem.getText()).toBe('Hello, WebdriverIO! How are you today?')})it('should render with mocked component function', async () => {getQuestionFn.mockReturnValue('Does this work?')render(html`<simple-greeting name="WebdriverIO" />`,document.body)const innerElem = await $('simple-greeting').$('p')expect(await innerElem.getText()).toBe('Hello, WebdriverIO! Does this work?')})})```</TabItem></Tabs>WebdriverIO just re-exports [`@vitest/spy`](https://www.npmjs.com/package/@vitest/spy) here which is a lightweight Jest compatible spy implementation that can be used with WebdriverIOs [`expect`](/docs/api/expect-webdriverio) matchers. You can find more documentation on these mock functions on the [Vitest project page](https://vitest.dev/api/mock.html).Of course, you can also install and import any other spy framework, e.g. [SinonJS](https://sinonjs.org/), as long as it supports the browser environment.## ModulesMock local modules or observe third-party-libraries, that are invoked in some other code, allowing you to test arguments, output or even redeclare its implementation.There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.### Mocking File ImportsLet's imagine our component is importing a utility method from a file to handle a click.```js title=utils.jsexport function handleClick () {// handler implementation}```In our component the click handler is used as following:```ts title=LitComponent.jsimport { handleClick } from './utils.js'@customElement('simple-button')export class SimpleButton extends LitElement {render() {return html`<button @click="${handleClick}">Click me!</button>`}}```To mock the `handleClick` from `utils.js` we can use the `mock` method in our test as following:```js title=LitComponent.test.jsimport { expect, $ } from '@wdio/globals'import { mock, fn } from '@wdio/browser-runner'import { html, render } from 'lit'import { SimpleButton } from './LitComponent.ts'import { handleClick } from './utils.js'/*** mock named export "handleClick" of `utils.ts` file*/mock('./utils.ts', () => ({handleClick: fn()}))describe('Simple Button Component Test', () => {it('call click handler', async () => {render(html`<simple-button />`, document.body)await $('simple-button').$('button').click()expect(handleClick).toHaveBeenCalledTimes(1)})})```### Mocking DependenciesSuppose we have a class that fetches users from our API. The class uses [`axios`](https://github.com/axios/axios) to call the API then returns the data attribute which contains all the users:```js title=users.jsimport axios from 'axios';class Users {static all() {return axios.get('/users.json').then(resp => resp.data)}}export default Users```Now, in order to test this method without actually hitting the API (and thus creating slow and fragile tests), we can use the `mock(...)` function to automatically mock the axios module.Once we mock the module we can provide a [`mockResolvedValue`](https://vitest.dev/api/mock.html#mockresolvedvalue) for `.get` that returns the data we want our test to assert against. In effect, we are saying that we want `axios.get('/users.json')` to return a fake response.```js title=users.test.jsimport axios from 'axios'; // imports defined mockimport { mock, fn } from '@wdio/browser-runner'import Users from './users.js'/*** mock default export of `axios` dependency*/mock('axios', () => ({default: {get: fn()}}))describe('User API', () => {it('should fetch users', async () => {const users = [{name: 'Bob'}]const resp = {data: users}axios.get.mockResolvedValue(resp)// or you could use the following depending on your use case:// axios.get.mockImplementation(() => Promise.resolve(resp))const data = await Users.all()expect(data).toEqual(users)})})```## PartialsSubsets of a module can be mocked and the rest of the module can keep their actual implementation:```js title=foo-bar-baz.jsexport const foo = 'foo';export const bar = () => 'bar';export default () => 'baz';```The original module will be passed into the mock factory which you can use to e.g. partially mock a dependency:```jsimport { mock, fn } from '@wdio/browser-runner'import defaultExport, { bar, foo } from './foo-bar-baz.js';mock('./foo-bar-baz.js', async (originalModule) => {// Mock the default export and named export 'foo'// and propagate named export from the original modulereturn {__esModule: true,...originalModule,default: fn(() => 'mocked baz'),foo: 'mocked foo',}})describe('partial mock', () => {it('should do a partial mock', () => {const defaultExportResult = defaultExport();expect(defaultExportResult).toBe('mocked baz');expect(defaultExport).toHaveBeenCalled();expect(foo).toBe('mocked foo');expect(bar()).toBe('bar');})})```## Manual MocksManual mocks are defined by writing a module in a `__mocks__/` (see also `automockDir` option) subdirectory. If the module you are mocking is a Node module (e.g.: `lodash`), the mock should be placed in the `__mocks__` directory and will be automatically mocked. There's no need to explicitly call `mock('module_name')`.Scoped modules (also known as scoped packages) can be mocked by creating a file in a directory structure that matches the name of the scoped module. For example, to mock a scoped module called `@scope/project-name`, create a file at `__mocks__/@scope/project-name.js`, creating the `@scope/` directory accordingly.```.├── config├── __mocks__│ ├── axios.js│ ├── lodash.js│ └── @scope│ └── project-name.js├── node_modules└── views```When a manual mock exists for a given module, WebdriverIO will use that module when explicitly calling `mock('moduleName')`. However, when automock is set to true, the manual mock implementation will be used instead of the automatically created mock, even if `mock('moduleName')` is not called. To opt out of this behavior you will need to explicitly call `unmock('moduleName')` in tests that should use the actual module implementation, e.g.:```jsimport { unmock } from '@wdio/browser-runner'unmock('lodash')```## HoistingIn order to get mocking to work in the browser, WebdriverIO rewrites the test files and hoists the mock calls above everything else (see also [this blog post](https://www.coolcomputerclub.com/posts/jest-hoist-await/) on the hoisting problem in Jest). This limits the way you can pass in variables into the mock resolver, e.g.:```js title=component.test.jsimport dep from 'dependency'const variable = 'foobar'/*** ❌ this fails as `dep` and `variable` are not defined inside the mock resolver*/mock('./some/module.ts', () => ({exportA: dep,exportB: variable}))```To fix this you have to define all used variables inside the resolver, e.g.:```js title=component.test.js/*** ✔️ this works as all variables are defined within the resolver*/mock('./some/module.ts', async () => {const dep = await import('dependency')const variable = 'foobar'return {exportA: dep,exportB: variable}})```## RequestsIf you are looking for mocking browser requests, e.g. API calls, head over to the [Request Mock and Spies](/docs/mocksandspies) section.