or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

asymmetric-matchers.mdcollection-string-matchers.mdconfiguration-extension.mdcore-matchers.mdexception-matchers.mdindex.mdnumeric-matchers.mdspy-mock-matchers.md
tile.json

spy-mock-matchers.mddocs/

0

# Spy and Mock Matchers

1

2

Verification matchers for Jest mock functions and spies, essential for testing function calls and interactions. These matchers allow you to verify that functions were called with the correct arguments, the right number of times, and in the expected order.

3

4

## Capabilities

5

6

### Basic Call Verification

7

8

#### toBeCalled / toHaveBeenCalled

9

10

Verifies that a mock function was called at least once.

11

12

```javascript { .api }

13

/**

14

* Checks if mock function was called at least once

15

*/

16

ExpectationObject.toBeCalled(): void;

17

18

/**

19

* Alias for toBeCalled - checks if mock function was called

20

*/

21

ExpectationObject.toHaveBeenCalled(): void;

22

```

23

24

**Usage Examples:**

25

26

```javascript

27

// Basic mock function testing

28

const mockFn = jest.fn();

29

mockFn();

30

expect(mockFn).toBeCalled();

31

expect(mockFn).toHaveBeenCalled(); // same as toBeCalled

32

33

// Testing event handlers

34

const onClickHandler = jest.fn();

35

const button = {

36

click: () => onClickHandler()

37

};

38

39

button.click();

40

expect(onClickHandler).toHaveBeenCalled();

41

42

// Testing callback functions

43

function processData(data, callback) {

44

// process data...

45

callback(data);

46

}

47

48

const callback = jest.fn();

49

processData({id: 1}, callback);

50

expect(callback).toHaveBeenCalled();

51

```

52

53

### Argument Verification

54

55

#### toBeCalledWith / toHaveBeenCalledWith

56

57

Verifies that a mock function was called with specific arguments at least once.

58

59

```javascript { .api }

60

/**

61

* Checks if mock function was called with specific arguments

62

* @param args - Expected arguments the function should have been called with

63

*/

64

ExpectationObject.toBeCalledWith(...args: any[]): void;

65

66

/**

67

* Alias for toBeCalledWith - checks function was called with specific arguments

68

* @param args - Expected arguments the function should have been called with

69

*/

70

ExpectationObject.toHaveBeenCalledWith(...args: any[]): void;

71

```

72

73

**Usage Examples:**

74

75

```javascript

76

const mockFn = jest.fn();

77

mockFn('hello', 42, {active: true});

78

79

expect(mockFn).toBeCalledWith('hello', 42, {active: true});

80

expect(mockFn).toHaveBeenCalledWith('hello', 42, {active: true});

81

82

// Testing API calls

83

const apiClient = {

84

get: jest.fn()

85

};

86

87

await apiClient.get('/users', {limit: 10});

88

expect(apiClient.get).toHaveBeenCalledWith('/users', {limit: 10});

89

90

// Testing with partial matching using asymmetric matchers

91

const logger = jest.fn();

92

logger('Error', 'Something went wrong', {timestamp: new Date()});

93

94

expect(logger).toHaveBeenCalledWith(

95

'Error',

96

'Something went wrong',

97

expect.objectContaining({timestamp: expect.any(Date)})

98

);

99

```

100

101

### Call Count Verification

102

103

#### toHaveBeenCalledTimes

104

105

Verifies that a mock function was called a specific number of times.

106

107

```javascript { .api }

108

/**

109

* Checks if mock function was called specific number of times

110

* @param number - Expected number of calls

111

*/

112

ExpectationObject.toHaveBeenCalledTimes(number: number): void;

113

```

114

115

**Usage Examples:**

116

117

```javascript

118

const mockFn = jest.fn();

119

120

// Initially not called

121

expect(mockFn).toHaveBeenCalledTimes(0);

122

123

mockFn();

124

expect(mockFn).toHaveBeenCalledTimes(1);

125

126

mockFn();

127

mockFn();

128

expect(mockFn).toHaveBeenCalledTimes(3);

129

130

// Testing initialization functions

131

const initializeApp = jest.fn();

132

const app = new Application();

133

app.init();

134

135

expect(initializeApp).toHaveBeenCalledTimes(1);

136

137

// Testing event listeners

138

const eventHandler = jest.fn();

139

const emitter = new EventEmitter();

140

emitter.on('data', eventHandler);

141

142

emitter.emit('data', 'test1');

143

emitter.emit('data', 'test2');

144

145

expect(eventHandler).toHaveBeenCalledTimes(2);

146

```

147

148

### Last Call Verification

149

150

#### lastCalledWith / toHaveBeenLastCalledWith

151

152

Verifies the arguments of the most recent call to a mock function.

153

154

```javascript { .api }

155

/**

156

* Checks if mock function was last called with specific arguments

157

* @param args - Expected arguments from the most recent call

158

*/

159

ExpectationObject.lastCalledWith(...args: any[]): void;

160

161

/**

162

* Alias for lastCalledWith - checks most recent call arguments

163

* @param args - Expected arguments from the most recent call

164

*/

165

ExpectationObject.toHaveBeenLastCalledWith(...args: any[]): void;

166

```

167

168

**Usage Examples:**

169

170

```javascript

171

const mockFn = jest.fn();

172

173

mockFn('first call');

174

mockFn('second call');

175

mockFn('third call');

176

177

expect(mockFn).lastCalledWith('third call');

178

expect(mockFn).toHaveBeenLastCalledWith('third call');

179

180

// Testing progressive updates

181

const updateProgress = jest.fn();

182

183

updateProgress('Starting...');

184

updateProgress('Processing...', 50);

185

updateProgress('Completed!', 100);

186

187

expect(updateProgress).toHaveBeenLastCalledWith('Completed!', 100);

188

expect(updateProgress).toHaveBeenCalledTimes(3);

189

190

// Testing state changes

191

const setState = jest.fn();

192

193

setState({loading: true});

194

setState({loading: false, data: []});

195

setState({loading: false, data: [1, 2, 3]});

196

197

expect(setState).toHaveBeenLastCalledWith({

198

loading: false,

199

data: [1, 2, 3]

200

});

201

```

202

203

## Advanced Usage Patterns

204

205

### Testing Function Compositions

206

207

```javascript

208

const mockTransform = jest.fn(x => x * 2);

209

const mockFilter = jest.fn(x => x > 5);

210

const mockMap = jest.fn(x => x.toString());

211

212

const pipeline = [1, 2, 3, 4, 5, 6]

213

.map(mockTransform)

214

.filter(mockFilter)

215

.map(mockMap);

216

217

// Verify each function was called the right number of times

218

expect(mockTransform).toHaveBeenCalledTimes(6);

219

expect(mockFilter).toHaveBeenCalledTimes(6);

220

expect(mockMap).toHaveBeenCalledTimes(3); // only items > 5 after transform

221

222

// Verify specific calls

223

expect(mockTransform).toHaveBeenCalledWith(1);

224

expect(mockTransform).toHaveBeenCalledWith(6);

225

expect(mockFilter).toHaveBeenCalledWith(12); // 6 * 2

226

expect(mockMap).toHaveBeenLastCalledWith(12);

227

```

228

229

### Testing Async Operations

230

231

```javascript

232

const mockCallback = jest.fn();

233

234

async function processAsync(items, callback) {

235

for (const item of items) {

236

await new Promise(resolve => setTimeout(resolve, 10));

237

callback(item);

238

}

239

}

240

241

await processAsync(['a', 'b', 'c'], mockCallback);

242

243

expect(mockCallback).toHaveBeenCalledTimes(3);

244

expect(mockCallback).toHaveBeenNthCalledWith(1, 'a');

245

expect(mockCallback).toHaveBeenNthCalledWith(2, 'b');

246

expect(mockCallback).toHaveBeenLastCalledWith('c');

247

```

248

249

### Testing Error Handling

250

251

```javascript

252

const mockErrorHandler = jest.fn();

253

const mockSuccessHandler = jest.fn();

254

255

function processWithHandlers(data) {

256

try {

257

if (!data) throw new Error('No data provided');

258

mockSuccessHandler(data);

259

} catch (error) {

260

mockErrorHandler(error);

261

}

262

}

263

264

// Test error case

265

processWithHandlers(null);

266

expect(mockErrorHandler).toHaveBeenCalledWith(

267

expect.objectContaining({message: 'No data provided'})

268

);

269

expect(mockSuccessHandler).not.toHaveBeenCalled();

270

271

// Reset mocks

272

mockErrorHandler.mockReset();

273

mockSuccessHandler.mockReset();

274

275

// Test success case

276

processWithHandlers({id: 1});

277

expect(mockSuccessHandler).toHaveBeenCalledWith({id: 1});

278

expect(mockErrorHandler).not.toHaveBeenCalled();

279

```

280

281

### Testing Class Methods

282

283

```javascript

284

class UserService {

285

constructor(apiClient) {

286

this.apiClient = apiClient;

287

}

288

289

async createUser(userData) {

290

const user = await this.apiClient.post('/users', userData);

291

this.logActivity('user_created', user.id);

292

return user;

293

}

294

295

logActivity(action, userId) {

296

// logging implementation

297

}

298

}

299

300

// Test with mocked dependencies

301

const mockApiClient = {

302

post: jest.fn().mockResolvedValue({id: 123, name: 'John'})

303

};

304

305

const userService = new UserService(mockApiClient);

306

userService.logActivity = jest.fn();

307

308

const userData = {name: 'John', email: 'john@example.com'};

309

const result = await userService.createUser(userData);

310

311

expect(mockApiClient.post).toHaveBeenCalledWith('/users', userData);

312

expect(userService.logActivity).toHaveBeenCalledWith('user_created', 123);

313

expect(mockApiClient.post).toHaveBeenCalledTimes(1);

314

```

315

316

## Integration with Asymmetric Matchers

317

318

Spy matchers work well with asymmetric matchers for flexible argument verification:

319

320

```javascript

321

const mockFn = jest.fn();

322

323

mockFn('test', {timestamp: new Date(), id: 123});

324

325

expect(mockFn).toHaveBeenCalledWith(

326

expect.any(String),

327

expect.objectContaining({

328

timestamp: expect.any(Date),

329

id: expect.any(Number)

330

})

331

);

332

```

333

334

## Negation Support

335

336

All spy matchers support negation:

337

338

```javascript

339

const mockFn = jest.fn();

340

341

expect(mockFn).not.toHaveBeenCalled();

342

343

mockFn('test');

344

expect(mockFn).not.toHaveBeenCalledWith('different');

345

expect(mockFn).not.toHaveBeenCalledTimes(2);

346

```

347

348

## Promise Support

349

350

Spy matchers work with promises when testing async mock functions:

351

352

```javascript

353

const asyncMock = jest.fn().mockResolvedValue('result');

354

355

await asyncMock('test');

356

357

await expect(Promise.resolve(asyncMock)).resolves.toHaveBeenCalledWith('test');

358

```