or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-testing.mdhooks.mdindex.mdmocking.mdrunner.md

mocking.mddocs/

0

# Mocking System

1

2

Comprehensive mocking system for functions and object methods with call tracking, implementation control, and restoration capabilities. The mocking system provides fine-grained control over function behavior during testing.

3

4

## Capabilities

5

6

### MockTracker

7

8

The main mocking interface accessed via the `mock` property. Provides methods for creating and managing various types of mocks.

9

10

```javascript { .api }

11

/**

12

* Main mocking interface for creating and managing mocks

13

*/

14

const mock: MockTracker;

15

16

interface MockTracker {

17

/** Create a function mock */

18

fn(original?: Function, implementation?: Function, options?: MockOptions): MockFunctionContext;

19

/** Mock an object method */

20

method(object: object, methodName: string, implementation?: Function, options?: MethodMockOptions): MockFunctionContext;

21

/** Mock an object getter */

22

getter(object: object, methodName: string, implementation?: Function, options?: MockOptions): MockFunctionContext;

23

/** Mock an object setter */

24

setter(object: object, methodName: string, implementation?: Function, options?: MockOptions): MockFunctionContext;

25

/** Reset all mock call tracking data */

26

reset(): void;

27

/** Restore all mocked functions to their originals */

28

restoreAll(): void;

29

}

30

```

31

32

### Function Mocking

33

34

Create mock functions for testing function behavior and call patterns.

35

36

```javascript { .api }

37

/**

38

* Create a function mock

39

* @param original - Original function to mock (optional)

40

* @param implementation - Mock implementation (optional)

41

* @param options - Mock configuration options

42

* @returns MockFunctionContext for controlling and inspecting the mock

43

*/

44

fn(original?: Function, implementation?: Function, options?: MockOptions): MockFunctionContext;

45

46

interface MockOptions {

47

/** Number of times mock should be active before restoring */

48

times?: number;

49

}

50

```

51

52

**Usage Examples:**

53

54

```javascript

55

import { mock } from "test";

56

57

// Basic function mock

58

const mockFn = mock.fn();

59

mockFn('hello', 'world');

60

console.log(mockFn.callCount()); // 1

61

62

// Mock with implementation

63

const add = mock.fn(null, (a, b) => a + b);

64

console.log(add(2, 3)); // 5

65

66

// Mock existing function

67

const originalFetch = fetch;

68

const mockFetch = mock.fn(originalFetch, async () => ({

69

json: async () => ({ success: true })

70

}));

71

72

// Temporary mock (auto-restores after 2 calls)

73

const tempMock = mock.fn(console.log, () => {}, { times: 2 });

74

tempMock('call 1'); // mock implementation

75

tempMock('call 2'); // mock implementation

76

tempMock('call 3'); // original console.log

77

```

78

79

### Method Mocking

80

81

Mock methods on existing objects while preserving the object structure.

82

83

```javascript { .api }

84

/**

85

* Mock an object method

86

* @param object - Target object containing the method

87

* @param methodName - Name of the method to mock

88

* @param implementation - Mock implementation (optional)

89

* @param options - Mock configuration options

90

* @returns MockFunctionContext for controlling and inspecting the mock

91

*/

92

method(object: object, methodName: string, implementation?: Function, options?: MethodMockOptions): MockFunctionContext;

93

94

interface MethodMockOptions extends MockOptions {

95

/** Mock as getter property */

96

getter?: boolean;

97

/** Mock as setter property */

98

setter?: boolean;

99

}

100

```

101

102

**Usage Examples:**

103

104

```javascript

105

import { mock } from "test";

106

107

// Mock object method

108

const user = {

109

name: 'Alice',

110

getName() { return this.name; }

111

};

112

113

const mockGetName = mock.method(user, 'getName', function() {

114

return 'Mocked Name';

115

});

116

117

console.log(user.getName()); // 'Mocked Name'

118

console.log(mockGetName.callCount()); // 1

119

120

// Mock with original function access

121

const fs = require('fs');

122

const mockReadFile = mock.method(fs, 'readFileSync', (path) => {

123

if (path === 'test.txt') return 'mocked content';

124

// Call original for other files

125

return mockReadFile.original(path);

126

});

127

128

// Mock getter/setter

129

const config = {

130

_timeout: 1000,

131

get timeout() { return this._timeout; },

132

set timeout(value) { this._timeout = value; }

133

};

134

135

mock.method(config, 'timeout', () => 5000, { getter: true });

136

console.log(config.timeout); // 5000

137

```

138

139

### Getter and Setter Mocking

140

141

Specialized methods for mocking property getters and setters.

142

143

```javascript { .api }

144

/**

145

* Mock an object getter

146

* @param object - Target object

147

* @param methodName - Property name

148

* @param implementation - Getter implementation

149

* @param options - Mock options

150

* @returns MockFunctionContext

151

*/

152

getter(object: object, methodName: string, implementation?: Function, options?: MockOptions): MockFunctionContext;

153

154

/**

155

* Mock an object setter

156

* @param object - Target object

157

* @param methodName - Property name

158

* @param implementation - Setter implementation

159

* @param options - Mock options

160

* @returns MockFunctionContext

161

*/

162

setter(object: object, methodName: string, implementation?: Function, options?: MockOptions): MockFunctionContext;

163

```

164

165

**Usage Examples:**

166

167

```javascript

168

import { mock } from "test";

169

170

const obj = {

171

_value: 42,

172

get value() { return this._value; },

173

set value(v) { this._value = v; }

174

};

175

176

// Mock getter

177

const mockGetter = mock.getter(obj, 'value', () => 999);

178

console.log(obj.value); // 999

179

180

// Mock setter

181

const mockSetter = mock.setter(obj, 'value', function(v) {

182

console.log(`Setting value to ${v}`);

183

this._value = v * 2;

184

});

185

186

obj.value = 10; // Logs: "Setting value to 10"

187

console.log(obj._value); // 20

188

```

189

190

## MockFunctionContext

191

192

Context object returned by all mock creation methods, providing control and inspection capabilities.

193

194

```javascript { .api }

195

interface MockFunctionContext {

196

/** Array of all function calls (read-only) */

197

calls: CallRecord[];

198

/** Get the total number of calls */

199

callCount(): number;

200

/** Change the mock implementation */

201

mockImplementation(implementation: Function): void;

202

/** Set implementation for a specific call number */

203

mockImplementationOnce(implementation: Function, onCall?: number): void;

204

/** Restore the original function */

205

restore(): void;

206

}

207

208

interface CallRecord {

209

arguments: any[];

210

result?: any;

211

error?: Error;

212

target?: any;

213

this?: any;

214

}

215

```

216

217

**Usage Examples:**

218

219

```javascript

220

import { mock } from "test";

221

222

const mockFn = mock.fn();

223

224

// Make some calls

225

mockFn('arg1', 'arg2');

226

mockFn(123);

227

mockFn();

228

229

// Inspect calls

230

console.log(mockFn.callCount()); // 3

231

console.log(mockFn.calls[0].arguments); // ['arg1', 'arg2']

232

console.log(mockFn.calls[1].arguments); // [123]

233

234

// Change implementation

235

mockFn.mockImplementation((x) => x * 2);

236

console.log(mockFn(5)); // 10

237

238

// One-time implementation

239

mockFn.mockImplementationOnce(() => 'special', 4);

240

mockFn(); // 'special' (5th call)

241

mockFn(); // back to x * 2 implementation

242

243

// Restore original

244

mockFn.restore();

245

```

246

247

### Call Inspection

248

249

Detailed inspection of mock function calls:

250

251

```javascript

252

import { mock } from "test";

253

254

const calculator = {

255

add(a, b) { return a + b; }

256

};

257

258

const mockAdd = mock.method(calculator, 'add');

259

260

// Make calls

261

calculator.add(2, 3);

262

calculator.add(10, 5);

263

264

// Inspect calls

265

const calls = mockAdd.calls;

266

267

calls.forEach((call, index) => {

268

console.log(`Call ${index + 1}:`);

269

console.log(` Arguments: ${call.arguments}`);

270

console.log(` Result: ${call.result}`);

271

console.log(` This context:`, call.this);

272

});

273

274

// Check specific calls

275

if (mockAdd.callCount() >= 2) {

276

const secondCall = calls[1];

277

if (secondCall.arguments[0] === 10 && secondCall.arguments[1] === 5) {

278

console.log('Second call was add(10, 5)');

279

}

280

}

281

```

282

283

## Global Mock Management

284

285

### Reset All Mocks

286

287

Clear call tracking data for all mocks without restoring implementations:

288

289

```javascript { .api }

290

/**

291

* Reset all mock call tracking data

292

*/

293

reset(): void;

294

```

295

296

**Usage Examples:**

297

298

```javascript

299

import { mock } from "test";

300

301

const mockFn1 = mock.fn();

302

const mockFn2 = mock.fn();

303

304

mockFn1('test');

305

mockFn2('test');

306

307

console.log(mockFn1.callCount()); // 1

308

console.log(mockFn2.callCount()); // 1

309

310

mock.reset();

311

312

console.log(mockFn1.callCount()); // 0

313

console.log(mockFn2.callCount()); // 0

314

// Functions still mocked, just call history cleared

315

```

316

317

### Restore All Mocks

318

319

Restore all mocked functions to their original implementations:

320

321

```javascript { .api }

322

/**

323

* Restore all mocked functions to their originals

324

*/

325

restoreAll(): void;

326

```

327

328

**Usage Examples:**

329

330

```javascript

331

import { mock } from "test";

332

333

const obj = {

334

method1() { return 'original1'; },

335

method2() { return 'original2'; }

336

};

337

338

mock.method(obj, 'method1', () => 'mocked1');

339

mock.method(obj, 'method2', () => 'mocked2');

340

341

console.log(obj.method1()); // 'mocked1'

342

console.log(obj.method2()); // 'mocked2'

343

344

mock.restoreAll();

345

346

console.log(obj.method1()); // 'original1'

347

console.log(obj.method2()); // 'original2'

348

```

349

350

## Advanced Patterns

351

352

### Conditional Mocking

353

354

Mock functions that behave differently based on arguments:

355

356

```javascript

357

import { mock } from "test";

358

359

const mockFetch = mock.fn(fetch, async (url, options) => {

360

if (url.includes('/api/users')) {

361

return { json: async () => [{ id: 1, name: 'Test User' }] };

362

}

363

if (url.includes('/api/error')) {

364

throw new Error('Network error');

365

}

366

// Call original fetch for other URLs

367

return fetch(url, options);

368

});

369

```

370

371

### Spy Pattern

372

373

Monitor function calls without changing behavior:

374

375

```javascript

376

import { mock } from "test";

377

378

const logger = {

379

log(message) {

380

console.log(`[LOG] ${message}`);

381

}

382

};

383

384

// Spy on logger.log (keep original behavior)

385

const logSpy = mock.method(logger, 'log', function(message) {

386

// Call original implementation

387

return logSpy.original.call(this, message);

388

});

389

390

logger.log('Hello'); // Still logs to console

391

console.log(logSpy.callCount()); // 1

392

console.log(logSpy.calls[0].arguments[0]); // 'Hello'

393

```

394

395

### Mock Chaining

396

397

Create complex mock setups:

398

399

```javascript

400

import { mock } from "test";

401

402

const api = {

403

get() { return Promise.resolve({ data: 'real data' }); },

404

post() { return Promise.resolve({ success: true }); }

405

};

406

407

// Chain multiple mocks

408

mock.method(api, 'get', () => Promise.resolve({ data: 'mock data' }))

409

mock.method(api, 'post', () => Promise.resolve({ success: false }));

410

411

// Test with mocked API

412

test('API interactions', async (t) => {

413

const getData = await api.get();

414

const postResult = await api.post();

415

416

if (getData.data !== 'mock data') {

417

throw new Error('GET mock failed');

418

}

419

if (postResult.success !== false) {

420

throw new Error('POST mock failed');

421

}

422

423

// Clean up

424

mock.restoreAll();

425

});

426

```

427

428

### Error Simulation

429

430

Mock functions to simulate error conditions:

431

432

```javascript

433

import { mock } from "test";

434

435

const fileSystem = {

436

readFile(path) {

437

// Original implementation

438

return fs.readFileSync(path, 'utf8');

439

}

440

};

441

442

// Mock to simulate file not found

443

const mockReadFile = mock.method(fileSystem, 'readFile', (path) => {

444

if (path === 'nonexistent.txt') {

445

const error = new Error('ENOENT: no such file or directory');

446

error.code = 'ENOENT';

447

throw error;

448

}

449

return 'file contents';

450

});

451

452

test('error handling', (t) => {

453

try {

454

fileSystem.readFile('nonexistent.txt');

455

throw new Error('Should have thrown');

456

} catch (error) {

457

if (error.code !== 'ENOENT') {

458

throw new Error('Wrong error type');

459

}

460

}

461

462

// Verify the error was tracked

463

if (mockReadFile.calls[0].error.code !== 'ENOENT') {

464

throw new Error('Error not tracked correctly');

465

}

466

});

467

```

468

469

## Best Practices

470

471

1. **Clean up mocks**: Always restore mocks after tests

472

2. **Use spies for monitoring**: Keep original behavior when you just need to track calls

473

3. **Mock at the right level**: Mock dependencies, not implementation details

474

4. **Test mock behavior**: Verify mocks are called with expected arguments

475

5. **Avoid over-mocking**: Only mock what's necessary for the test

476

477

```javascript

478

import { mock, afterEach } from "test";

479

480

// Clean up after each test

481

afterEach(() => {

482

mock.restoreAll();

483

});

484

485

test('user service', (t) => {

486

const database = {

487

findUser: (id) => ({ id, name: 'Real User' })

488

};

489

490

// Mock external dependency

491

const mockFindUser = mock.method(database, 'findUser',

492

(id) => ({ id, name: 'Test User' })

493

);

494

495

const userService = new UserService(database);

496

const user = userService.getUser(123);

497

498

// Test the result

499

if (user.name !== 'Test User') {

500

throw new Error('Service failed');

501

}

502

503

// Verify mock was called correctly

504

if (mockFindUser.callCount() !== 1) {

505

throw new Error('Database not called');

506

}

507

if (mockFindUser.calls[0].arguments[0] !== 123) {

508

throw new Error('Wrong user ID passed');

509

}

510

});

511

```