# vitest/prefer-called-exactly-once-with

> Require `toHaveBeenCalledExactlyOnceWith()` over separate call count and argument checks

`toHaveBeenCalledOnce()` followed by `toHaveBeenCalledWith(...)` on the same mock takes two assertions to say one thing: the mock ran once, with these arguments. `toHaveBeenCalledExactlyOnceWith(...)` says it in one line.

The pair is reported when both assertions are in the same block, in either order. Assertions with `.not` are ignored.

`--fix-dangerously` replaces the pair with one `toHaveBeenCalledExactlyOnceWith(...)` call. `--fix` doesn't.

{/* Generated by src/codegen/lint-rule-docs.ts. Do not edit this section. */}

## Configure

Off by default. To turn it on:

```toml bunfig.toml
[lint.rules]
"vitest/prefer-called-exactly-once-with" = "error" # or "warn"
```

{/* End of the generated section. */}

## Examples

Reported:

{/* bad */}
```ts
import { expect, test, vi } from "vitest";

test("saves the draft", () => {
  const save = vi.fn();
  autosave("draft", save);
  expect(save).toHaveBeenCalledOnce();
  expect(save).toHaveBeenCalledWith("draft");
});
```

Not reported:

{/* good */}
```ts
import { expect, test, vi } from "vitest";

test("saves the draft", () => {
  const save = vi.fn();
  autosave("draft", save);
  expect(save).toHaveBeenCalledExactlyOnceWith("draft");
});
```

A `mockClear()`, `mockReset()`, or `mockRestore()` on the mock between the two assertions means they're about different calls, so they aren't a pair:

{/* good */}
```ts
import { expect, test, vi } from "vitest";

test("saves again after an edit", () => {
  const save = vi.fn();
  autosave("draft", save);
  expect(save).toHaveBeenCalledOnce();

  save.mockClear();
  autosave("edited", save);
  expect(save).toHaveBeenCalledWith("edited");
});
```
