0
# Mock Configuration
1
2
Mock class and request/response configuration for detailed HTTP mock setup. This module provides the core classes for defining complex request matching criteria and response behaviors using pook's fluent API.
3
4
## Capabilities
5
6
### Mock Class
7
8
The primary interface for creating and configuring HTTP mocks with comprehensive request matching and response definition capabilities.
9
10
```python { .api }
11
class Mock:
12
"""
13
Mock is used to declare and compose HTTP request/response mock
14
definition and matching expectations with fluent API DSL.
15
"""
16
17
def __init__(self, url=None, method=None, path=None, headers=None,
18
header_present=None, headers_present=None, type=None,
19
content=None, params=None, param_exists=None,
20
params_exists=None, body=None, json=None, jsonschema=None,
21
xml=None, file=None, times=None, persist=None, delay=None,
22
callback=None, reply=None, response_status=None,
23
response_headers=None, response_type=None, response_body=None,
24
response_json=None, response_xml=None, request=None, response=None):
25
"""
26
Parameters:
27
- url (str): URL to match
28
- method (str): HTTP method name to match
29
- path (str): URL path to match
30
- headers (dict): Header values to match
31
- header_present (str): Matches if a header is present
32
- headers_present (list|tuple): Matches if multiple headers are present
33
- type (str): Matches MIME Content-Type header
34
- content (str): Same as type argument
35
- params (dict): Matches the given URL params
36
- param_exists (str): Matches if a given URL param exists
37
- params_exists (list|tuple): Matches if given URL params exist
38
- body (str|regex): Matches the payload body
39
- json (dict|list|str|regex): Matches JSON payload body
40
- jsonschema (dict|str): Matches payload body against JSONSchema
41
- xml (str|regex): Matches XML payload body
42
- file (str): Disk file path to load body from
43
- times (int): Mock TTL or maximum number of matches
44
- persist (bool): Enable persistent mode
45
- delay (int): Optional network delay simulation
46
- callback (function): Callback function called when mock is matched
47
- reply (int): Mock response status. Defaults to 200
48
- response_status (int): Alias to reply param
49
- response_headers (dict): Response headers to use
50
- response_type (str): Response MIME type expression or alias
51
- response_body (str): Response body to use
52
- response_json (dict|list|str): Response JSON to use
53
- response_xml (str): XML body string to use
54
- request (Request): Optional Request mock definition object
55
- response (Response): Optional Response mock definition object
56
"""
57
58
# Request Configuration Methods
59
def url(self, url):
60
"""
61
Defines mock URL to match.
62
63
Parameters:
64
- url (str|regex): URL pattern to match
65
66
Returns:
67
Mock: Self for method chaining
68
"""
69
70
def method(self, method):
71
"""
72
Defines HTTP method to match.
73
74
Parameters:
75
- method (str): HTTP method name (GET, POST, PUT, etc.)
76
77
Returns:
78
Mock: Self for method chaining
79
"""
80
81
def path(self, path):
82
"""
83
Defines URL path to match.
84
85
Parameters:
86
- path (str|regex): URL path pattern to match
87
88
Returns:
89
Mock: Self for method chaining
90
"""
91
92
def header(self, name, value):
93
"""
94
Defines header to match.
95
96
Parameters:
97
- name (str): Header name
98
- value (str|regex): Header value or pattern
99
100
Returns:
101
Mock: Self for method chaining
102
"""
103
104
def headers(self, headers):
105
"""
106
Defines multiple headers to match.
107
108
Parameters:
109
- headers (dict): Dictionary of header name-value pairs
110
111
Returns:
112
Mock: Self for method chaining
113
"""
114
115
def header_present(self, *names):
116
"""
117
Matches if headers are present (regardless of value).
118
119
Parameters:
120
- *names (str): Header names to check for presence
121
122
Returns:
123
Mock: Self for method chaining
124
"""
125
126
def headers_present(self, headers):
127
"""
128
Matches if multiple headers are present (regardless of values).
129
130
Parameters:
131
- headers (list|tuple): List of header names to check for presence
132
133
Returns:
134
Mock: Self for method chaining
135
"""
136
137
def type(self, value):
138
"""
139
Defines Content-Type header to match.
140
141
Parameters:
142
- value (str): Content-Type value or alias (json, xml, form, etc.)
143
144
Returns:
145
Mock: Self for method chaining
146
"""
147
148
def content(self, value):
149
"""
150
Alias to type() method for Content-Type matching.
151
152
Parameters:
153
- value (str): Content-Type value or alias
154
155
Returns:
156
Mock: Self for method chaining
157
"""
158
159
def param(self, name, value):
160
"""
161
Defines URL parameter to match.
162
163
Parameters:
164
- name (str): Parameter name
165
- value (str|regex): Parameter value or pattern
166
167
Returns:
168
Mock: Self for method chaining
169
"""
170
171
def params(self, params):
172
"""
173
Defines multiple URL parameters to match.
174
175
Parameters:
176
- params (dict): Dictionary of parameter name-value pairs
177
178
Returns:
179
Mock: Self for method chaining
180
"""
181
182
def param_exists(self, name, allow_empty=False):
183
"""
184
Checks if URL parameter exists.
185
186
Parameters:
187
- name (str): Parameter name to check
188
- allow_empty (bool): Allow empty parameter values
189
190
Returns:
191
Mock: Self for method chaining
192
"""
193
194
def body(self, body):
195
"""
196
Defines body data to match.
197
198
Parameters:
199
- body (str|bytes|regex): Request body content or pattern
200
201
Returns:
202
Mock: Self for method chaining
203
"""
204
205
def json(self, json_data):
206
"""
207
Defines JSON body to match.
208
209
Parameters:
210
- json_data (dict|list|str|regex): JSON data or pattern
211
212
Returns:
213
Mock: Self for method chaining
214
"""
215
216
def jsonschema(self, schema):
217
"""
218
Defines JSONSchema for body matching.
219
220
Parameters:
221
- schema (dict|str): JSONSchema definition
222
223
Returns:
224
Mock: Self for method chaining
225
"""
226
227
def xml(self, xml_data):
228
"""
229
Defines XML body to match.
230
231
Parameters:
232
- xml_data (str|regex): XML content or pattern
233
234
Returns:
235
Mock: Self for method chaining
236
"""
237
238
def file(self, path):
239
"""
240
Reads body from disk file.
241
242
Parameters:
243
- path (str): File path to read body content from
244
245
Returns:
246
Mock: Self for method chaining
247
"""
248
249
# Mock Behavior Configuration
250
def times(self, times=1):
251
"""
252
Defines TTL limit for mock (how many times it can be matched).
253
254
Parameters:
255
- times (int): Number of times mock can be matched
256
257
Returns:
258
Mock: Self for method chaining
259
"""
260
261
def persist(self, status=None):
262
"""
263
Enables persistent mode (mock never expires).
264
265
Parameters:
266
- status (bool, optional): Enable/disable persistence
267
268
Returns:
269
Mock: Self for method chaining
270
"""
271
272
def delay(self, delay=1000):
273
"""
274
Delays network response simulation.
275
276
Parameters:
277
- delay (int): Delay in milliseconds
278
279
Returns:
280
Mock: Self for method chaining
281
"""
282
283
def callback(self, *callbacks):
284
"""
285
Registers callbacks for matched requests.
286
287
Parameters:
288
- *callbacks (function): Callback functions to register
289
290
Returns:
291
Mock: Self for method chaining
292
"""
293
294
def error(self, error):
295
"""
296
Defines error exception to raise when mock is matched.
297
298
Parameters:
299
- error (Exception): Exception instance to raise
300
301
Returns:
302
Mock: Self for method chaining
303
"""
304
305
def add_matcher(self, matcher):
306
"""
307
Adds custom matcher function to mock.
308
309
Parameters:
310
- matcher (function): Custom matcher function that accepts request parameter
311
312
Returns:
313
Mock: Self for method chaining
314
"""
315
316
def use(self, *matchers):
317
"""
318
Adds multiple matcher functions to mock.
319
320
Parameters:
321
- *matchers (function): Matcher functions to add
322
323
Returns:
324
Mock: Self for method chaining
325
"""
326
327
def filter(self, *filters):
328
"""
329
Adds request filter functions for pre-processing.
330
331
Parameters:
332
- *filters (function): Filter functions to add
333
334
Returns:
335
Mock: Self for method chaining
336
"""
337
338
def map(self, *mappers):
339
"""
340
Adds request mapper functions for request transformation.
341
342
Parameters:
343
- *mappers (function): Mapper functions to add
344
345
Returns:
346
Mock: Self for method chaining
347
"""
348
349
# Response Configuration
350
def reply(self, status=200, **kw):
351
"""
352
Defines mock response.
353
354
Parameters:
355
- status (int): Response status code
356
- **kw: Additional response configuration
357
358
Returns:
359
Mock: Self for method chaining
360
"""
361
362
def status(self, code=200):
363
"""
364
Defines response status code.
365
366
Parameters:
367
- code (int): HTTP status code
368
369
Returns:
370
Mock: Self for method chaining
371
"""
372
373
def response(self, status=200, **kw):
374
"""
375
Alias to reply() method.
376
377
Parameters:
378
- status (int): Response status code
379
- **kw: Additional response configuration
380
381
Returns:
382
Mock: Self for method chaining
383
"""
384
385
# State Methods
386
def isdone(self):
387
"""
388
Returns if mock has been matched/completed.
389
390
Returns:
391
bool: True if mock is done
392
"""
393
394
def ismatched(self):
395
"""
396
Returns if mock has been matched at least once.
397
398
Returns:
399
bool: True if mock has been matched
400
"""
401
402
def match(self, request):
403
"""
404
Matches outgoing HTTP request against this mock.
405
406
Parameters:
407
- request: HTTP request to match
408
409
Returns:
410
bool: True if request matches this mock
411
"""
412
413
# Properties
414
@property
415
def done(self):
416
"""True if mock is done/matched."""
417
418
@property
419
def matched(self):
420
"""True if mock has been matched at least once."""
421
422
@property
423
def total_matches(self):
424
"""Total number of times mock has been matched."""
425
426
@property
427
def calls(self):
428
"""Number of mock matched calls."""
429
430
@property
431
def matches(self):
432
"""Number of times this mock has been matched (alias to calls)."""
433
```
434
435
Usage examples:
436
437
```python
438
import pook
439
440
# Basic mock configuration
441
mock = pook.Mock('https://api.example.com/users')
442
mock.method('GET').header('Authorization', 'Bearer token').reply(200)
443
444
# Fluent API chaining
445
pook.Mock() \
446
.url('https://api.example.com/data') \
447
.method('POST') \
448
.json({'type': 'test'}) \
449
.header('Content-Type', 'application/json') \
450
.reply(201) \
451
.json({'id': 123, 'status': 'created'})
452
453
# Advanced matching with regex
454
import re
455
pook.Mock() \
456
.url(re.compile(r'https://api\.example\.com/users/\d+')) \
457
.method('PUT') \
458
.jsonschema({'type': 'object', 'properties': {'name': {'type': 'string'}}}) \
459
.reply(200)
460
461
# Context manager usage
462
with pook.Mock('https://api.example.com/temp') as mock:
463
mock.get().reply(200).json({'temp': True})
464
# Mock is automatically activated and cleaned up
465
```
466
467
### Request Class
468
469
Represents request mock expectations with detailed matching criteria for HTTP requests.
470
471
```python { .api }
472
class Request:
473
"""
474
Request object representing the request mock expectation DSL.
475
"""
476
477
def __init__(self, method="GET", url=None, headers=None, query=None,
478
body=None, json=None, xml=None):
479
"""
480
Parameters:
481
- method (str): HTTP method to match. Defaults to "GET"
482
- url (str): URL request to intercept and match
483
- headers (dict): HTTP headers to match
484
- query (dict): URL query params to match
485
- body (bytes|regex): Request body payload to match
486
- json (str|dict|list): JSON payload body structure to match
487
- xml (str): XML payload data structure to match
488
"""
489
490
def copy(self):
491
"""
492
Copies the current Request object for side-effects purposes.
493
494
Returns:
495
Request: Copy of this request object
496
"""
497
498
# Properties
499
@property
500
def method(self):
501
"""HTTP method to match."""
502
503
@property
504
def headers(self):
505
"""HTTP headers to match (HTTPHeaderDict)."""
506
507
@property
508
def url(self):
509
"""URL request to intercept and match (parsed URL or regex)."""
510
511
@property
512
def rawurl(self):
513
"""Raw URL string representation."""
514
515
@property
516
def query(self):
517
"""URL query params to match (dict)."""
518
519
@property
520
def body(self):
521
"""Request body payload to match (bytes)."""
522
523
@property
524
def json(self):
525
"""JSON payload body structure to match (parsed JSON)."""
526
527
@property
528
def xml(self):
529
"""XML payload data structure to match (str)."""
530
531
@property
532
def extra(self):
533
"""Additional extra data (dict)."""
534
```
535
536
Usage examples:
537
538
```python
539
import pook
540
541
# Using Request object directly
542
request = pook.Request(
543
method='POST',
544
url='https://api.example.com/users',
545
headers={'Content-Type': 'application/json'},
546
json={'name': 'John', 'email': 'john@example.com'}
547
)
548
549
# Using with Mock
550
mock = pook.Mock(request=request)
551
mock.reply(201).json({'id': 123})
552
553
# Request copying for variations
554
base_request = pook.Request(method='GET', url='https://api.example.com/data')
555
specific_request = base_request.copy()
556
```
557
558
### Response Class
559
560
Defines HTTP mock response configuration with chainable DSL interface for comprehensive response setup.
561
562
```python { .api }
563
class Response:
564
"""
565
Response is used to declare and compose HTTP mock response
566
fields with chainable DSL interface.
567
"""
568
569
def __init__(self, status=200, headers=None, body=None, json=None,
570
xml=None, type=None, file=None):
571
"""
572
Parameters:
573
- status (int): HTTP response status code. Defaults to 200
574
- headers (dict): HTTP response headers
575
- body (str|bytes): HTTP response body
576
- json (str|dict|list): HTTP response JSON body
577
- xml (str): HTTP response XML body
578
- type (str): HTTP response content MIME type
579
- file (str): File path to HTTP body response
580
"""
581
582
def status(self, code=200):
583
"""
584
Defines response status code.
585
586
Parameters:
587
- code (int): HTTP status code
588
589
Returns:
590
Response: Self for method chaining
591
"""
592
593
def header(self, key, value):
594
"""
595
Defines new response header.
596
597
Parameters:
598
- key (str): Header name
599
- value (str): Header value
600
601
Returns:
602
Response: Self for method chaining
603
"""
604
605
def headers(self, headers):
606
"""
607
Defines multiple response headers.
608
609
Parameters:
610
- headers (dict): Dictionary of header name-value pairs
611
612
Returns:
613
Response: Self for method chaining
614
"""
615
616
def set(self, header, value):
617
"""
618
Defines new response header (alias to header()).
619
620
Parameters:
621
- header (str): Header name
622
- value (str): Header value
623
624
Returns:
625
Response: Self for method chaining
626
"""
627
628
def type(self, name):
629
"""
630
Defines Content-Type header.
631
632
Parameters:
633
- name (str): MIME type or alias (json, xml, html, etc.)
634
635
Returns:
636
Response: Self for method chaining
637
"""
638
639
def content(self, name):
640
"""
641
Alias to type() method for Content-Type.
642
643
Parameters:
644
- name (str): MIME type or alias
645
646
Returns:
647
Response: Self for method chaining
648
"""
649
650
def body(self, body, chunked=False):
651
"""
652
Defines response body data.
653
654
Parameters:
655
- body (str|bytes): Response body content
656
- chunked (bool): Enable chunked transfer encoding
657
658
Returns:
659
Response: Self for method chaining
660
"""
661
662
def json(self, data):
663
"""
664
Defines mock response JSON body.
665
666
Parameters:
667
- data (dict|list|str): JSON data to serialize
668
669
Returns:
670
Response: Self for method chaining
671
"""
672
673
def xml(self, xml_data):
674
"""
675
Defines mock response XML body.
676
677
Parameters:
678
- xml_data (str): XML content
679
680
Returns:
681
Response: Self for method chaining
682
"""
683
684
def file(self, path):
685
"""
686
Defines response body from file contents.
687
688
Parameters:
689
- path (str): File path to read response body from
690
691
Returns:
692
Response: Self for method chaining
693
"""
694
695
# Properties
696
@property
697
def mock(self):
698
"""Reference to mock instance (Mock)."""
699
```
700
701
Usage examples:
702
703
```python
704
import pook
705
706
# Using Response object directly
707
response = pook.Response(status=201)
708
response.json({'id': 123, 'name': 'John'}).header('Location', '/users/123')
709
710
# Using with Mock
711
mock = pook.Mock('https://api.example.com/users', response=response)
712
713
# Chained response configuration
714
pook.get('https://api.example.com/data') \
715
.reply(200) \
716
.type('application/json') \
717
.json({'data': [1, 2, 3]}) \
718
.header('Cache-Control', 'no-cache')
719
720
# File-based response
721
pook.get('https://api.example.com/large-file') \
722
.reply(200) \
723
.type('application/octet-stream') \
724
.file('/path/to/large-file.bin')
725
```
726
727
## MIME Type Constants
728
729
Predefined MIME type aliases for convenient content type specification:
730
731
```python
732
# Available type aliases
733
'text' → 'text/plain'
734
'html' → 'text/html'
735
'json' → 'application/json'
736
'xml' → 'application/xml'
737
'urlencoded' → 'application/x-www-form-urlencoded'
738
'form' → 'application/x-www-form-urlencoded'
739
'form-data' → 'application/x-www-form-urlencoded'
740
```
741
742
Usage examples:
743
744
```python
745
# Using type aliases
746
pook.post('https://api.example.com/form') \
747
.type('form') \
748
.body('name=John&email=john@example.com') \
749
.reply(200)
750
751
# Using full MIME types
752
pook.get('https://api.example.com/data') \
753
.reply(200) \
754
.type('application/vnd.api+json') \
755
.json({'data': []})
756
```
757
758
## Advanced Configuration Patterns
759
760
### Complex Request Matching
761
762
```python
763
import pook
764
import re
765
766
# Multiple criteria matching
767
pook.post('https://api.example.com/webhooks') \
768
.header('X-Webhook-Secret', 'secret123') \
769
.header('User-Agent', re.compile(r'MyApp/\d+\.\d+')) \
770
.json({'event': re.compile(r'user\.(created|updated)')}) \
771
.reply(200)
772
773
# JSONSchema validation
774
schema = {
775
"type": "object",
776
"properties": {
777
"name": {"type": "string"},
778
"age": {"type": "number", "minimum": 0}
779
},
780
"required": ["name"]
781
}
782
pook.post('https://api.example.com/users') \
783
.jsonschema(schema) \
784
.reply(201)
785
```
786
787
### Response Scenarios
788
789
```python
790
# Multiple response behaviors
791
mock = pook.get('https://api.example.com/flaky')
792
mock.times(2).reply(500).json({'error': 'Server error'})
793
mock.reply(200).json({'data': 'success'})
794
795
# Conditional responses with callbacks
796
def validate_request(request, mock):
797
if 'admin' in request.headers.get('Authorization', ''):
798
mock.reply(200).json({'role': 'admin'})
799
else:
800
mock.reply(403).json({'error': 'Forbidden'})
801
802
pook.get('https://api.example.com/profile') \
803
.callback(validate_request)
804
```