or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdhttp-client.mdhttp-utilities.mdindex.mdrequest-response-mocking.mdtest-doubles.mdtest-sandbox.mdvalidation-helpers.md

test-doubles.mddocs/

0

# Test Doubles and Mocking

1

2

Complete Sinon.js integration for spies, stubs, and mocks with enhanced TypeScript experience and improved stubbing utilities.

3

4

## Capabilities

5

6

### Sinon Integration

7

8

Complete Sinon.js library re-export with full TypeScript support.

9

10

```typescript { .api }

11

/**

12

* Complete Sinon.js library for creating test doubles

13

* Includes spies, stubs, mocks, and fake timers

14

*/

15

const sinon: sinon.SinonStatic;

16

17

/**

18

* Sinon spy type definition for TypeScript

19

*/

20

type SinonSpy = sinon.SinonSpy;

21

```

22

23

**Usage Examples:**

24

25

```typescript

26

import { sinon } from "@loopback/testlab";

27

28

// Creating spies

29

const spy = sinon.spy();

30

const objectSpy = sinon.spy(console, 'log');

31

32

// Creating stubs

33

const stub = sinon.stub();

34

stub.returns("mocked value");

35

stub.withArgs("specific").returns("specific response");

36

37

// Creating mocks

38

const mock = sinon.mock(console);

39

mock.expects("log").once().withArgs("Hello");

40

41

// Fake timers

42

const clock = sinon.useFakeTimers();

43

clock.tick(1000);

44

clock.restore();

45

```

46

47

### Enhanced Stub Instance Creation

48

49

Improved stub instance creation with better TypeScript support and stubs accessor.

50

51

```typescript { .api }

52

/**

53

* Creates a new object with the given functions as the prototype and stubs all

54

* implemented functions with enhanced TypeScript support

55

* @param constructor - Object or class to stub

56

* @returns A stubbed version with stubs accessor

57

*/

58

function createStubInstance<TType extends object>(

59

constructor: sinon.StubbableType<TType>

60

): StubbedInstanceWithSinonAccessor<TType>;

61

62

/**

63

* Type for stubbed instances with additional stubs accessor

64

* Provides both the stubbed interface and access to Sinon stub methods

65

*/

66

type StubbedInstanceWithSinonAccessor<T> = T & {

67

stubs: sinon.SinonStubbedInstance<T>;

68

};

69

```

70

71

**Usage Examples:**

72

73

```typescript

74

import { createStubInstance } from "@loopback/testlab";

75

76

class UserService {

77

async findUser(id: string): Promise<User> {

78

// Implementation

79

}

80

81

async createUser(data: UserData): Promise<User> {

82

// Implementation

83

}

84

}

85

86

// Create stubbed instance

87

const userServiceStub = createStubInstance(UserService);

88

89

// Configure stubs - both approaches work

90

userServiceStub.findUser.resolves({id: "123", name: "Alice"});

91

userServiceStub.stubs.findUser.resolves({id: "123", name: "Alice"});

92

93

// Use as normal instance

94

const user = await userServiceStub.findUser("123");

95

96

// Access stub methods for verification

97

expect(userServiceStub.stubs.findUser).to.have.been.calledWith("123");

98

```

99

100

### Spy Capabilities

101

102

Comprehensive spy functionality for monitoring function calls.

103

104

```typescript { .api }

105

// Spy creation methods (from Sinon)

106

sinon.spy(): sinon.SinonSpy;

107

sinon.spy(target: any, property: string): sinon.SinonSpy;

108

sinon.spy(func: Function): sinon.SinonSpy;

109

110

// Spy interface

111

interface SinonSpy {

112

(): any;

113

called: boolean;

114

callCount: number;

115

calledOnce: boolean;

116

calledTwice: boolean;

117

calledThrice: boolean;

118

firstCall: sinon.SinonSpyCall;

119

secondCall: sinon.SinonSpyCall;

120

thirdCall: sinon.SinonSpyCall;

121

lastCall: sinon.SinonSpyCall;

122

calledBefore(anotherSpy: sinon.SinonSpy): boolean;

123

calledAfter(anotherSpy: sinon.SinonSpy): boolean;

124

calledOn(obj: any): boolean;

125

alwaysCalledOn(obj: any): boolean;

126

calledWith(...args: any[]): boolean;

127

alwaysCalledWith(...args: any[]): boolean;

128

calledWithExactly(...args: any[]): boolean;

129

alwaysCalledWithExactly(...args: any[]): boolean;

130

neverCalledWith(...args: any[]): boolean;

131

threw(): boolean;

132

threw(exception: string | Function): boolean;

133

alwaysThrew(): boolean;

134

alwaysThrew(exception: string | Function): boolean;

135

returned(value: any): boolean;

136

alwaysReturned(value: any): boolean;

137

restore(): void;

138

reset(): void;

139

getCalls(): sinon.SinonSpyCall[];

140

}

141

```

142

143

### Stub Capabilities

144

145

Advanced stubbing functionality with method chaining and conditional responses.

146

147

```typescript { .api }

148

// Stub creation methods (from Sinon)

149

sinon.stub(): sinon.SinonStub;

150

sinon.stub(obj: any): sinon.SinonStubbedInstance<any>;

151

sinon.stub(obj: any, property: string): sinon.SinonStub;

152

153

// Stub interface (extends SinonSpy)

154

interface SinonStub extends SinonSpy {

155

returns(value: any): sinon.SinonStub;

156

returnsArg(index: number): sinon.SinonStub;

157

returnsThis(): sinon.SinonStub;

158

resolves(value?: any): sinon.SinonStub;

159

rejects(error?: any): sinon.SinonStub;

160

throws(error?: Error | string): sinon.SinonStub;

161

callsArg(index: number): sinon.SinonStub;

162

callsArgWith(index: number, ...args: any[]): sinon.SinonStub;

163

yields(...args: any[]): sinon.SinonStub;

164

yieldsTo(property: string, ...args: any[]): sinon.SinonStub;

165

withArgs(...args: any[]): sinon.SinonStub;

166

onCall(n: number): sinon.SinonStub;

167

onFirstCall(): sinon.SinonStub;

168

onSecondCall(): sinon.SinonStub;

169

onThirdCall(): sinon.SinonStub;

170

}

171

```

172

173

**Usage Examples:**

174

175

```typescript

176

import { sinon, expect } from "@loopback/testlab";

177

178

// Basic stubbing

179

const stub = sinon.stub();

180

stub.returns("default");

181

stub.withArgs("special").returns("special case");

182

183

expect(stub()).to.equal("default");

184

expect(stub("special")).to.equal("special case");

185

186

// Promise stubbing

187

const asyncStub = sinon.stub();

188

asyncStub.resolves("success");

189

asyncStub.withArgs("error").rejects(new Error("failed"));

190

191

const result = await asyncStub();

192

expect(result).to.equal("success");

193

194

// Object method stubbing

195

const obj = { method: () => "original" };

196

const methodStub = sinon.stub(obj, "method");

197

methodStub.returns("stubbed");

198

199

expect(obj.method()).to.equal("stubbed");

200

methodStub.restore();

201

```

202

203

### Mock Capabilities

204

205

Mock objects with expectations and verification.

206

207

```typescript { .api }

208

// Mock creation (from Sinon)

209

sinon.mock(obj: any): sinon.SinonMock;

210

211

// Mock interface

212

interface SinonMock {

213

expects(method: string): sinon.SinonExpectation;

214

restore(): void;

215

verify(): void;

216

}

217

218

// Expectation interface

219

interface SinonExpectation {

220

atLeast(n: number): sinon.SinonExpectation;

221

atMost(n: number): sinon.SinonExpectation;

222

never(): sinon.SinonExpectation;

223

once(): sinon.SinonExpectation;

224

twice(): sinon.SinonExpectation;

225

thrice(): sinon.SinonExpectation;

226

exactly(n: number): sinon.SinonExpectation;

227

withArgs(...args: any[]): sinon.SinonExpectation;

228

withExactArgs(...args: any[]): sinon.SinonExpectation;

229

returns(value: any): sinon.SinonExpectation;

230

throws(error?: Error | string): sinon.SinonExpectation;

231

}

232

```

233

234

**Usage Examples:**

235

236

```typescript

237

import { sinon } from "@loopback/testlab";

238

239

const logger = { log: (msg: string) => console.log(msg) };

240

241

// Create mock with expectations

242

const mock = sinon.mock(logger);

243

mock.expects("log").once().withArgs("Hello World");

244

245

// Use the mocked object

246

logger.log("Hello World");

247

248

// Verify expectations

249

mock.verify(); // Throws if expectations not met

250

mock.restore();

251

```

252

253

### Fake Timers

254

255

Control time and async behavior in tests.

256

257

```typescript { .api }

258

// Timer methods (from Sinon)

259

sinon.useFakeTimers(): sinon.SinonFakeTimers;

260

sinon.useFakeTimers(config: Partial<sinon.SinonFakeTimersConfig>): sinon.SinonFakeTimers;

261

262

interface SinonFakeTimers {

263

tick(ms: number): void;

264

next(): void;

265

runAll(): void;

266

restore(): void;

267

reset(): void;

268

}

269

```

270

271

**Usage Examples:**

272

273

```typescript

274

import { sinon, expect } from "@loopback/testlab";

275

276

// Test with fake timers

277

const clock = sinon.useFakeTimers();

278

let called = false;

279

280

setTimeout(() => { called = true; }, 1000);

281

282

expect(called).to.be.false();

283

clock.tick(1000);

284

expect(called).to.be.true();

285

286

clock.restore();

287

```