or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-mocking.mdfixtures.mdindex.mdmock-creation.md

fixtures.mddocs/

0

# Pytest Fixtures

1

2

pytest-mock provides MockerFixture instances through pytest fixtures at multiple scopes, enabling flexible mock management across different test organization patterns. Each fixture provides the same MockerFixture interface but with different lifetimes and cleanup behaviors.

3

4

## Capabilities

5

6

### Function-Scoped Fixture

7

8

The default mocker fixture provides a MockerFixture instance that's created fresh for each test function and automatically cleaned up afterwards.

9

10

```python { .api }

11

@pytest.fixture

12

def mocker(pytestconfig) -> Generator[MockerFixture, None, None]:

13

"""

14

Function-scoped mocker fixture (default scope).

15

16

Creates a new MockerFixture instance for each test function.

17

All mocks are automatically stopped after the test completes.

18

19

Yields:

20

MockerFixture instance for the test function

21

"""

22

```

23

24

Usage examples:

25

26

```python

27

def test_function_scope_basic(mocker):

28

# Fresh mocker instance for this test

29

mock_func = mocker.patch('os.path.exists')

30

mock_func.return_value = True

31

32

result = check_file_exists('test.txt')

33

assert result is True

34

mock_func.assert_called_once_with('test.txt')

35

# Mock automatically cleaned up after test

36

37

def test_function_scope_independent(mocker):

38

# Completely independent mocker instance

39

mock_func = mocker.patch('os.path.exists')

40

mock_func.return_value = False

41

42

result = check_file_exists('other.txt')

43

assert result is False

44

# No interference from previous test

45

46

class TestWithFunctionScope:

47

def test_method_one(self, mocker):

48

# Fresh mocker for this method

49

spy = mocker.spy(Calculator, 'add')

50

calc = Calculator()

51

result = calc.add(2, 3)

52

spy.assert_called_once_with(2, 3)

53

54

def test_method_two(self, mocker):

55

# Independent mocker instance

56

mock_calc = mocker.create_autospec(Calculator)

57

mock_calc.add.return_value = 100

58

assert mock_calc.add(1, 1) == 100

59

```

60

61

### Class-Scoped Fixture

62

63

The class_mocker fixture provides a MockerFixture instance shared across all test methods in a test class, with cleanup after the class completes.

64

65

```python { .api }

66

@pytest.fixture(scope="class")

67

def class_mocker(pytestconfig) -> Generator[MockerFixture, None, None]:

68

"""

69

Class-scoped mocker fixture.

70

71

Creates one MockerFixture instance shared by all test methods

72

in a test class. Mocks persist across methods and are cleaned

73

up after the class completes.

74

75

Yields:

76

MockerFixture instance for the test class

77

"""

78

```

79

80

Usage examples:

81

82

```python

83

class TestDatabaseOperations:

84

def test_connection_setup(self, class_mocker):

85

# Mock persists for entire class

86

self.db_mock = class_mocker.patch('myapp.database.connect')

87

self.db_mock.return_value = 'mock_connection'

88

89

setup_database()

90

self.db_mock.assert_called_once()

91

92

def test_query_execution(self, class_mocker):

93

# Same mocker instance, mocks still active

94

query_mock = class_mocker.patch('myapp.database.execute_query')

95

query_mock.return_value = [{'id': 1, 'name': 'test'}]

96

97

results = run_query('SELECT * FROM users')

98

99

# db_mock from previous test is still active

100

assert self.db_mock.called

101

query_mock.assert_called_once()

102

assert len(results) == 1

103

104

def test_connection_cleanup(self, class_mocker):

105

# All mocks from class still available

106

cleanup_mock = class_mocker.patch('myapp.database.disconnect')

107

108

cleanup_database()

109

110

# Can verify interactions across the whole class

111

assert self.db_mock.call_count >= 1

112

cleanup_mock.assert_called_once()

113

114

# All mocks automatically cleaned up after class completes

115

116

# Different class gets fresh mocker instance

117

class TestFileOperations:

118

def test_independent_mocking(self, class_mocker):

119

# Completely separate from TestDatabaseOperations

120

file_mock = class_mocker.patch('builtins.open')

121

file_mock.return_value.__enter__.return_value.read.return_value = 'content'

122

123

data = read_file('test.txt')

124

assert data == 'content'

125

```

126

127

### Module-Scoped Fixture

128

129

The module_mocker fixture provides a MockerFixture instance shared across all tests in a module, with cleanup after the module completes.

130

131

```python { .api }

132

@pytest.fixture(scope="module")

133

def module_mocker(pytestconfig) -> Generator[MockerFixture, None, None]:

134

"""

135

Module-scoped mocker fixture.

136

137

Creates one MockerFixture instance shared by all tests

138

in a module. Mocks persist across functions and classes

139

and are cleaned up after the module completes.

140

141

Yields:

142

MockerFixture instance for the test module

143

"""

144

```

145

146

Usage examples:

147

148

```python

149

# test_api_integration.py

150

151

# Module-level setup with module_mocker

152

@pytest.fixture(scope="module", autouse=True)

153

def setup_api_mocks(module_mocker):

154

"""Setup common mocks for entire module."""

155

# Mock external API calls for all tests in module

156

module_mocker.patch('requests.get', side_effect=mock_api_response)

157

module_mocker.patch('requests.post', side_effect=mock_api_post)

158

159

# Mock authentication for all tests

160

auth_mock = module_mocker.patch('myapp.auth.verify_token')

161

auth_mock.return_value = True

162

163

return module_mocker

164

165

def test_get_user_data(module_mocker):

166

# Uses module-level mocks automatically

167

user_data = fetch_user_data(user_id=123)

168

169

# Can add test-specific mocks too

170

cache_mock = module_mocker.patch('myapp.cache.get')

171

cached_data = get_cached_user(user_id=123)

172

173

assert user_data['id'] == 123

174

cache_mock.assert_called_once()

175

176

def test_create_user(module_mocker):

177

# Same module-level mocks still active

178

new_user = create_user({'name': 'Test User'})

179

180

# requests.post mock from setup is used

181

assert new_user['status'] == 'created'

182

183

class TestUserManagement:

184

def test_update_user(self, module_mocker):

185

# Module-level mocks available in classes too

186

result = update_user(123, {'name': 'Updated'})

187

assert result['success'] is True

188

189

def test_delete_user(self, module_mocker):

190

# All module mocks persist across class methods

191

result = delete_user(123)

192

assert result['deleted'] is True

193

194

# All module-level mocks cleaned up when module completes

195

```

196

197

### Package-Scoped Fixture

198

199

The package_mocker fixture provides a MockerFixture instance shared across all tests in a Python package, with cleanup after the package completes.

200

201

```python { .api }

202

@pytest.fixture(scope="package")

203

def package_mocker(pytestconfig) -> Generator[MockerFixture, None, None]:

204

"""

205

Package-scoped mocker fixture.

206

207

Creates one MockerFixture instance shared by all tests

208

in a package. Mocks persist across modules and are

209

cleaned up after the package completes.

210

211

Yields:

212

MockerFixture instance for the test package

213

"""

214

```

215

216

Usage examples:

217

218

```python

219

# tests/conftest.py - Package-level configuration

220

@pytest.fixture(scope="package", autouse=True)

221

def package_setup(package_mocker):

222

"""Setup package-wide mocks and configuration."""

223

# Mock external services for entire test package

224

package_mocker.patch('myapp.external.payment_service.charge')

225

package_mocker.patch('myapp.external.email_service.send')

226

227

# Mock environment configuration

228

package_mocker.patch.dict('os.environ', {

229

'DATABASE_URL': 'sqlite:///:memory:',

230

'REDIS_URL': 'redis://localhost:6379/15',

231

'API_KEY': 'test-api-key'

232

})

233

234

return package_mocker

235

236

# tests/test_payments.py

237

def test_process_payment(package_mocker):

238

# Uses package-level payment service mock

239

result = process_payment(amount=100, card_token='tok_123')

240

assert result['status'] == 'success'

241

242

# tests/test_notifications.py

243

def test_send_notification(package_mocker):

244

# Uses package-level email service mock

245

send_welcome_email('user@example.com')

246

# Email mock is already configured at package level

247

248

# tests/integration/test_workflows.py

249

def test_complete_workflow(package_mocker):

250

# All package-level mocks available in subdirectories

251

workflow = CompleteUserWorkflow()

252

result = workflow.execute(user_data={'email': 'test@example.com'})

253

254

# Payment and email mocks from package level are used

255

assert result['payment_processed'] is True

256

assert result['welcome_sent'] is True

257

```

258

259

### Session-Scoped Fixture

260

261

The session_mocker fixture provides a MockerFixture instance shared across the entire test session, with cleanup after all tests complete.

262

263

```python { .api }

264

@pytest.fixture(scope="session")

265

def session_mocker(pytestconfig) -> Generator[MockerFixture, None, None]:

266

"""

267

Session-scoped mocker fixture.

268

269

Creates one MockerFixture instance shared by all tests

270

in the session. Mocks persist across all packages and

271

modules and are cleaned up after the session completes.

272

273

Yields:

274

MockerFixture instance for the test session

275

"""

276

```

277

278

Usage examples:

279

280

```python

281

# conftest.py at root of test suite

282

@pytest.fixture(scope="session", autouse=True)

283

def global_test_setup(session_mocker):

284

"""Setup session-wide mocks for external dependencies."""

285

# Mock third-party services for entire test session

286

session_mocker.patch('stripe.api_resources.Charge.create')

287

session_mocker.patch('boto3.client') # Mock AWS services

288

session_mocker.patch('redis.Redis.from_url')

289

290

# Mock time-based functions for consistent testing

291

import datetime

292

fixed_time = datetime.datetime(2023, 1, 1, 12, 0, 0)

293

session_mocker.patch('datetime.datetime.now', return_value=fixed_time)

294

295

return session_mocker

296

297

# Any test file in the session

298

def test_stripe_integration(session_mocker):

299

# Uses session-level stripe mock automatically

300

charge = create_payment_charge(amount=1000)

301

assert charge['status'] == 'succeeded'

302

303

def test_aws_s3_upload(session_mocker):

304

# Uses session-level boto3 mock automatically

305

result = upload_file_to_s3('test.txt', 'content')

306

assert result['success'] is True

307

308

# Different package, same session mocks

309

def test_redis_caching(session_mocker):

310

# Uses session-level redis mock automatically

311

cache_key = 'test:key'

312

set_cache(cache_key, 'value')

313

value = get_cache(cache_key)

314

assert value == 'value'

315

316

def test_time_dependent_logic(session_mocker):

317

# Uses session-level datetime mock - consistent time across all tests

318

timestamp = get_current_timestamp()

319

assert timestamp == '2023-01-01T12:00:00'

320

```

321

322

### Fixture Scope Comparison

323

324

```python

325

# Scope lifecycles and use cases

326

327

def test_scope_demonstration():

328

"""

329

Fixture Scopes (from shortest to longest lived):

330

331

1. function (default) - New MockerFixture per test function

332

- Use for: Isolated test mocks, no shared state needed

333

- Cleanup: After each test function

334

335

2. class - One MockerFixture per test class

336

- Use for: Shared setup within related test methods

337

- Cleanup: After test class completes

338

339

3. module - One MockerFixture per test module

340

- Use for: Expensive mocks, module-wide configuration

341

- Cleanup: After test module completes

342

343

4. package - One MockerFixture per test package

344

- Use for: Package-wide external service mocks

345

- Cleanup: After test package completes

346

347

5. session - One MockerFixture for entire test session

348

- Use for: Global mocks, third-party service mocks

349

- Cleanup: After all tests complete

350

"""

351

352

# Choosing the right scope:

353

def test_choosing_fixture_scope():

354

"""

355

Guidelines for fixture scope selection:

356

357

- function: Default choice, ensures test isolation

358

- class: When test methods need shared mock state

359

- module: For expensive-to-create mocks used across module

360

- package: For mocking external dependencies across packages

361

- session: For global mocks that should never change

362

363

Trade-offs:

364

- Longer scopes = better performance, less isolation

365

- Shorter scopes = better isolation, more setup overhead

366

"""

367

```