or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

assertions.mdindex.mdmocking.mdproperty-testing.mdtest-aspects.mdtest-environment.mdtest-execution.mdtest-specifications.md

mocking.mddocs/

0

# Mocking Framework

1

2

Complete mocking system for creating controlled test doubles with expectation-based verification.

3

4

## Capabilities

5

6

### Mock Class

7

8

Base class for creating service mocks with expectation management.

9

10

```scala { .api }

11

/**

12

* Base class for service mocks

13

* @tparam M - Service type (usually Has[Service])

14

*/

15

abstract class Mock[-M <: Has[_]] {

16

/** Creates expectation for specific capability */

17

def expects[I, A](capability: Capability[M, I, A]): Expectation[I]

18

19

/** Composes this mock with another mock */

20

def compose[M1 <: Has[_]](that: Mock[M1]): Mock[M with M1]

21

}

22

```

23

24

### Expectation System

25

26

Expectation types for defining mock behavior and verification.

27

28

```scala { .api }

29

/**

30

* Represents an expectation for mock method calls

31

* @tparam I - Input parameter type

32

*/

33

sealed trait Expectation[-I] {

34

/** Combines with another expectation (both must be satisfied) */

35

def and[I1 <: I](that: Expectation[I1]): Expectation[I1]

36

37

/** Alternative expectation (either can be satisfied) */

38

def or[I1 <: I](that: Expectation[I1]): Expectation[I1]

39

40

/** Repeats expectation for specified range of calls */

41

def repeats(range: Range): Expectation[I]

42

43

/** Specifies return value for matching calls */

44

def returns[A](value: A): Expectation[I]

45

46

/** Specifies effectful return value */

47

def returnsM[R, E, A](effect: ZIO[R, E, A]): Expectation[I]

48

49

/** Specifies that calls should throw error */

50

def throws[E](error: E): Expectation[I]

51

52

/** Specifies that calls should die with throwable */

53

def dies(throwable: Throwable): Expectation[I]

54

}

55

56

object Expectation {

57

/** Expectation that matches specific value */

58

def value[A](assertion: Assertion[A]): Expectation[A]

59

60

/** Expectation that matches any value */

61

val unit: Expectation[Unit]

62

63

/** Expectation that never matches */

64

val never: Expectation[Any]

65

}

66

```

67

68

### Capability System

69

70

Capability represents a mockable method or operation of a service.

71

72

```scala { .api }

73

/**

74

* Represents a capability (method) that can be mocked

75

* @tparam R - Service environment type

76

* @tparam I - Input parameter type

77

* @tparam A - Return type

78

*/

79

case class Capability[R <: Has[_], I, A](name: String) {

80

/** Creates expectation for this capability */

81

def apply(assertion: Assertion[I]): Expectation[I]

82

}

83

84

object Capability {

85

/** Creates capability with given name */

86

def of[M <: Has[_], I, A](name: String): Capability[M, I, A]

87

}

88

```

89

90

### Mock Result Types

91

92

Result types for specifying mock return values and behaviors.

93

94

```scala { .api }

95

/**

96

* Result of a mock method call

97

*/

98

sealed trait Result

99

100

object Result {

101

/** Successful result with value */

102

def succeed[A](value: A): Result

103

104

/** Failed result with error */

105

def fail[E](error: E): Result

106

107

/** Death result with throwable */

108

def die(throwable: Throwable): Result

109

110

/** Empty/unit result */

111

val unit: Result

112

}

113

```

114

115

### Proxy System

116

117

System for creating dynamic proxy instances from mocks.

118

119

```scala { .api }

120

/**

121

* Proxy factory for creating service instances from mocks

122

*/

123

object Proxy {

124

/** Creates service proxy from mock */

125

def make[R <: Has[_]](mock: Mock[R]): ULayer[R]

126

}

127

```

128

129

### Built-in Service Mocks

130

131

Pre-built mocks for standard ZIO services.

132

133

```scala { .api }

134

/**

135

* Mock for Clock service

136

*/

137

object MockClock extends Mock[Clock] {

138

/** currentTime capability */

139

val CurrentTime: Capability[Clock, Any, OffsetDateTime]

140

141

/** currentDateTime capability */

142

val CurrentDateTime: Capability[Clock, Any, OffsetDateTime]

143

144

/** nanoTime capability */

145

val NanoTime: Capability[Clock, Any, Long]

146

147

/** sleep capability */

148

val Sleep: Capability[Clock, Duration, Unit]

149

}

150

151

/**

152

* Mock for Console service

153

*/

154

object MockConsole extends Mock[Console] {

155

/** putStr capability */

156

val PutStr: Capability[Console, String, Unit]

157

158

/** putStrLn capability */

159

val PutStrLn: Capability[Console, String, Unit]

160

161

/** putStrErr capability */

162

val PutStrErr: Capability[Console, String, Unit]

163

164

/** getStrLn capability */

165

val GetStrLn: Capability[Console, Any, String]

166

}

167

168

/**

169

* Mock for Random service

170

*/

171

object MockRandom extends Mock[Random] {

172

/** nextBoolean capability */

173

val NextBoolean: Capability[Random, Any, Boolean]

174

175

/** nextBytes capability */

176

val NextBytes: Capability[Random, Int, Chunk[Byte]]

177

178

/** nextDouble capability */

179

val NextDouble: Capability[Random, Any, Double]

180

181

/** nextFloat capability */

182

val NextFloat: Capability[Random, Any, Float]

183

184

/** nextInt capability */

185

val NextInt: Capability[Random, Any, Int]

186

187

/** nextIntBounded capability */

188

val NextIntBounded: Capability[Random, Int, Int]

189

190

/** nextLong capability */

191

val NextLong: Capability[Random, Any, Long]

192

}

193

194

/**

195

* Mock for System service

196

*/

197

object MockSystem extends Mock[System] {

198

/** env capability */

199

val Env: Capability[System, String, Option[String]]

200

201

/** property capability */

202

val Property: Capability[System, String, Option[String]]

203

204

/** lineSeparator capability */

205

val LineSeparator: Capability[System, Any, String]

206

}

207

```

208

209

## Usage Examples

210

211

### Basic Mock Usage

212

213

```scala

214

import zio.test._

215

import zio.test.mock._

216

217

// Define service interface

218

trait UserService {

219

def getUser(id: String): Task[User]

220

def createUser(user: User): Task[String]

221

}

222

223

// Create mock object

224

object MockUserService extends Mock[Has[UserService]] {

225

object GetUser extends Effect[String, Throwable, User]

226

object CreateUser extends Effect[User, Throwable, String]

227

228

val compose: URLayer[Has[Proxy], Has[UserService]] =

229

ZLayer.fromService { proxy =>

230

new UserService {

231

def getUser(id: String) = proxy(GetUser, id)

232

def createUser(user: User) = proxy(CreateUser, user)

233

}

234

}

235

}

236

237

// Use in tests

238

test("user service mock") {

239

val mockLayer = MockUserService.GetUser(

240

Expectation.value(equalTo("123")).returns(User("123", "John"))

241

)

242

243

val program = for {

244

userService <- ZIO.service[UserService]

245

user <- userService.getUser("123")

246

} yield user

247

248

assertM(program)(hasField("name", _.name, equalTo("John")))

249

.provideLayer(mockLayer)

250

}

251

```

252

253

### Complex Expectations

254

255

```scala

256

test("complex mock expectations") {

257

val mockLayer =

258

MockUserService.GetUser(

259

Expectation.value(equalTo("user1")).returns(User("user1", "Alice"))

260

) &&

261

MockUserService.GetUser(

262

Expectation.value(equalTo("user2")).returns(User("user2", "Bob"))

263

) &&

264

MockUserService.CreateUser(

265

Expectation.value(hasField("name", _.name, startsWith("Test")))

266

.returns("new-id-123")

267

.repeats(1 to 3)

268

)

269

270

val program = for {

271

service <- ZIO.service[UserService]

272

user1 <- service.getUser("user1")

273

user2 <- service.getUser("user2")

274

id1 <- service.createUser(User("", "Test User 1"))

275

id2 <- service.createUser(User("", "Test User 2"))

276

} yield (user1, user2, id1, id2)

277

278

assertM(program) {

279

case (u1, u2, id1, id2) =>

280

assert(u1.name)(equalTo("Alice")) &&

281

assert(u2.name)(equalTo("Bob")) &&

282

assert(id1)(equalTo("new-id-123")) &&

283

assert(id2)(equalTo("new-id-123"))

284

}.provideLayer(mockLayer)

285

}

286

```

287

288

### Service Mocks with Built-ins

289

290

```scala

291

test("built-in service mocks") {

292

val clockMock = MockClock.CurrentTime(

293

Expectation.unit.returns(OffsetDateTime.now())

294

) ++ MockClock.Sleep(

295

Expectation.value(equalTo(1.second)).returns(())

296

)

297

298

val consoleMock = MockConsole.PutStrLn(

299

Expectation.value(equalTo("Hello")).returns(())

300

) ++ MockConsole.GetStrLn(

301

Expectation.unit.returns("input")

302

)

303

304

val program = for {

305

_ <- clock.currentTime

306

_ <- clock.sleep(1.second)

307

_ <- putStrLn("Hello")

308

input <- getStrLn

309

} yield input

310

311

assertM(program)(equalTo("input"))

312

.provideLayer(clockMock ++ consoleMock)

313

}

314

```

315

316

### Error and Failure Expectations

317

318

```scala

319

test("mock failures and errors") {

320

val mockLayer = MockUserService.GetUser(

321

Expectation.value(equalTo("missing")).throws(new RuntimeException("User not found"))

322

) ++ MockUserService.CreateUser(

323

Expectation.value(hasField("name", _.name, isEmpty))

324

.fails(ValidationError("Name cannot be empty"))

325

)

326

327

val program1 = ZIO.service[UserService].flatMap(_.getUser("missing"))

328

val program2 = ZIO.service[UserService].flatMap(_.createUser(User("", "")))

329

330

assertM(program1.run)(dies(hasMessage(containsString("User not found")))) &&

331

assertM(program2.run)(fails(isSubtype[ValidationError]))

332

.provideLayer(mockLayer)

333

}

334

```

335

336

### Verification and Call Counting

337

338

```scala

339

test("call verification") {

340

val mockLayer = MockUserService.GetUser(

341

Expectation.value(anything).returns(User("", "")).repeats(2 to 4)

342

)

343

344

val program = for {

345

service <- ZIO.service[UserService]

346

_ <- service.getUser("1")

347

_ <- service.getUser("2")

348

_ <- service.getUser("3")

349

} yield ()

350

351

assertM(program)(isUnit).provideLayer(mockLayer)

352

}

353

```