0
# Argument Matching
1
2
Sophisticated argument matching system with calledWith() extension for creating expectations based on specific argument patterns.
3
4
## Capabilities
5
6
### CalledWith Extension
7
8
The calledWith method allows creating argument-specific expectations on mock functions, enabling precise behavior definition based on input parameters.
9
10
```typescript { .api }
11
/**
12
* Creates argument-specific expectation for mock function calls
13
* @param args - Expected arguments that can be literal values or matchers
14
* @returns Jest mock instance for chaining additional expectations
15
*/
16
calledWith(...args: [...MatchersOrLiterals<Parameters<T>>]): jest.Mock<T>;
17
```
18
19
**Usage Examples:**
20
21
```typescript
22
import { mock, any, anyString, anyNumber } from "jest-mock-extended";
23
24
interface UserService {
25
updateUser: (id: string, data: UserData, options?: UpdateOptions) => Promise<User>;
26
sendNotification: (userId: string, message: string, priority: number) => void;
27
}
28
29
const userService = mock<UserService>();
30
31
// Literal argument matching
32
userService.updateUser
33
.calledWith("user123", { name: "John" }, { validate: true })
34
.mockResolvedValue({ id: "user123", name: "John" });
35
36
// Mixed literal and matcher arguments
37
userService.updateUser
38
.calledWith("admin", any(), { admin: true })
39
.mockResolvedValue({ id: "admin", name: "Administrator" });
40
41
// Matcher-only arguments
42
userService.sendNotification
43
.calledWith(anyString(), anyString(), anyNumber())
44
.mockReturnValue(undefined);
45
46
// Multiple expectations for same function
47
userService.updateUser
48
.calledWith(anyString(), { status: "inactive" }, any())
49
.mockRejectedValue(new Error("Cannot update inactive user"));
50
```
51
52
### Matcher Arguments
53
54
Arguments in calledWith can be literal values or matcher objects that implement asymmetric matching patterns.
55
56
```typescript { .api }
57
/**
58
* Type defining arguments that can be either literal values or matcher objects
59
*/
60
type MatchersOrLiterals<Y extends any[]> = {
61
[K in keyof Y]: MatcherLike<Y[K]> | Y[K]
62
};
63
64
/**
65
* Interface for matcher objects that implement Jest asymmetric matcher protocol
66
*/
67
interface MatcherLike<T> {
68
asymmetricMatch(other: unknown): boolean;
69
toString(): string;
70
getExpectedType?(): string;
71
toAsymmetricMatcher?(): string;
72
}
73
```
74
75
**Usage Examples:**
76
77
```typescript
78
import { mock, any, anyString, anyObject, isA, arrayIncludes } from "jest-mock-extended";
79
80
interface DataProcessor {
81
processItems: (items: Item[], config: ProcessConfig) => ProcessResult;
82
validateInput: (data: any, schema: ValidationSchema) => boolean;
83
}
84
85
const processor = mock<DataProcessor>();
86
87
// Complex matcher combinations
88
processor.processItems
89
.calledWith(
90
arrayIncludes({ type: "premium" }), // Array must include premium item
91
{
92
strict: true,
93
timeout: anyNumber(),
94
filters: anyObject()
95
}
96
)
97
.mockReturnValue({ success: true, processedCount: 5 });
98
99
// Class instance matching
100
class CustomError extends Error {
101
constructor(public code: number, message: string) {
102
super(message);
103
}
104
}
105
106
processor.validateInput
107
.calledWith(any(), isA(ValidationSchema))
108
.mockReturnValue(true);
109
```
110
111
### CalledWith Function Creator
112
113
Creates a Jest mock function with calledWith extension functionality, providing low-level access to the argument matching system.
114
115
```typescript { .api }
116
/**
117
* Creates a Jest mock function with calledWith extension
118
* @param param - Destructured configuration parameter with fallback implementation
119
* @returns Mock function with argument-specific expectation capabilities
120
*/
121
const calledWithFn: <T extends FunctionLike>({
122
fallbackMockImplementation,
123
}?: { fallbackMockImplementation?: T }) => CalledWithMock<T>;
124
```
125
126
**Usage Examples:**
127
128
```typescript
129
import { calledWithFn, anyString, any } from "jest-mock-extended";
130
131
type ApiFunction = (method: string, url: string, data?: any) => Promise<Response>;
132
133
// Create mock function with calledWith extension
134
const apiFunc = calledWithFn<ApiFunction>({
135
fallbackMockImplementation: () => Promise.reject(new Error("Unmocked call"))
136
});
137
138
// Set up argument-specific expectations
139
apiFunc.calledWith("GET", anyString(), undefined)
140
.mockResolvedValue(new Response("GET success"));
141
142
apiFunc.calledWith("POST", "/api/users", any())
143
.mockResolvedValue(new Response("POST success"));
144
145
// Test the mock function
146
expect(await apiFunc("GET", "/api/data")).resolves.toBeDefined();
147
expect(await apiFunc("POST", "/api/users", { name: "John" })).resolves.toBeDefined();
148
149
// Unmocked calls will use fallback implementation
150
expect(apiFunc("DELETE", "/api/users/1")).rejects.toThrow("Unmocked call");
151
```
152
153
### Function Mock Creation
154
155
Standalone function mock creation with calledWith functionality for testing individual functions.
156
157
```typescript { .api }
158
/**
159
* Creates a Jest function mock with calledWith extension
160
* @returns Typed mock function with argument matching capabilities
161
*/
162
function mockFn<T extends FunctionLike>(): CalledWithMock<T> & T;
163
```
164
165
**Usage Examples:**
166
167
```typescript
168
import { mockFn, anyString, any } from "jest-mock-extended";
169
170
// Type definition for the function
171
type ApiCall = (
172
method: "GET" | "POST" | "PUT" | "DELETE",
173
url: string,
174
data?: any
175
) => Promise<ApiResponse>;
176
177
// Create typed mock function
178
const apiCall = mockFn<ApiCall>();
179
180
// Set up method-specific behavior
181
apiCall
182
.calledWith("GET", anyString(), undefined)
183
.mockResolvedValue({ status: 200, data: {} });
184
185
apiCall
186
.calledWith("POST", "/users", any())
187
.mockResolvedValue({ status: 201, data: { id: "new-user" } });
188
189
apiCall
190
.calledWith("DELETE", anyString(), undefined)
191
.mockResolvedValue({ status: 204, data: null });
192
193
// Test the mock
194
expect(await apiCall("GET", "/users")).toEqual({ status: 200, data: {} });
195
expect(await apiCall("POST", "/users", { name: "John" })).toEqual({
196
status: 201,
197
data: { id: "new-user" }
198
});
199
200
// Verify call expectations
201
expect(apiCall).toHaveBeenCalledWith("GET", "/users", undefined);
202
expect(apiCall).toHaveBeenCalledWith("POST", "/users", { name: "John" });
203
```
204
205
### Advanced Argument Patterns
206
207
Complex argument matching patterns for sophisticated testing scenarios.
208
209
**Usage Examples:**
210
211
```typescript
212
import { mock, captor, matches, anyString, any } from "jest-mock-extended";
213
214
interface EventEmitter {
215
emit: (event: string, data: any) => void;
216
on: (event: string, handler: (data: any) => void) => void;
217
}
218
219
const emitter = mock<EventEmitter>();
220
221
// Argument capturing
222
const eventCaptor = captor<string>();
223
const dataCaptor = captor<any>();
224
225
emitter.emit.calledWith(eventCaptor, dataCaptor).mockReturnValue(undefined);
226
227
emitter.emit("user:created", { id: "123", name: "John" });
228
229
// Access captured values
230
expect(eventCaptor.value).toBe("user:created");
231
expect(dataCaptor.value).toEqual({ id: "123", name: "John" });
232
233
// Custom matcher with complex logic
234
const isValidEmail = matches<string>((email) =>
235
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
236
);
237
238
interface EmailValidator {
239
validate: (email: string, domain?: string) => boolean;
240
}
241
242
const validator = mock<EmailValidator>();
243
244
validator.validate
245
.calledWith(isValidEmail, anyString())
246
.mockReturnValue(true);
247
248
validator.validate
249
.calledWith(matches((email) => !email.includes("@")), any())
250
.mockReturnValue(false);
251
252
// Test validation
253
expect(validator.validate("user@example.com", "example.com")).toBe(true);
254
expect(validator.validate("invalid-email", "example.com")).toBe(false);
255
```