8
8
ContextManager ,
9
9
GeneratorContextManager ,
10
10
)
11
- from .core import DecoyCore , StubCore
11
+ from .core import DecoyCore , StubCore , PropCore
12
12
from .types import ClassT , ContextValueT , FuncT , ReturnT
13
13
14
14
# ensure decoy does not pollute pytest tracebacks
@@ -19,7 +19,7 @@ class Decoy:
19
19
"""Decoy mock factory and state container.
20
20
21
21
You should create a new Decoy instance before each test and call
22
- [reset][decoy.Decoy.reset] after each test. If you use the
22
+ [` reset` ][decoy.Decoy.reset] after each test. If you use the
23
23
[`decoy` pytest fixture][decoy.pytest_plugin.decoy], this is done
24
24
automatically. See the [setup guide](../#setup) for more details.
25
25
@@ -92,7 +92,7 @@ def create_decoy(
92
92
"""Create a class mock for `spec`.
93
93
94
94
!!! warning "Deprecated since v1.6.0"
95
- Use [decoy.Decoy.mock][ ] with the `cls` parameter, instead.
95
+ Use [`mock`][ decoy.Decoy.mock] with the `cls` parameter, instead.
96
96
"""
97
97
warn (
98
98
"decoy.create_decoy is deprecated; use decoy.mock(cls=...) instead." ,
@@ -111,7 +111,7 @@ def create_decoy_func(
111
111
"""Create a function mock for `spec`.
112
112
113
113
!!! warning "Deprecated since v1.6.0"
114
- Use [decoy.Decoy.mock][ ] with the `func` parameter, instead.
114
+ Use [`mock`][ decoy.Decoy.mock] with the `func` parameter, instead.
115
115
"""
116
116
warn (
117
117
"decoy.create_decoy_func is deprecated; use decoy.mock(func=...) instead." ,
@@ -127,7 +127,7 @@ def when(
127
127
* ,
128
128
ignore_extra_args : bool = False ,
129
129
) -> "Stub[ReturnT]" :
130
- """Create a [Stub][decoy.Stub] configuration using a rehearsal call.
130
+ """Create a [` Stub` ][decoy.Stub] configuration using a rehearsal call.
131
131
132
132
See [stubbing usage guide](../usage/when/) for more details.
133
133
@@ -138,8 +138,9 @@ def when(
138
138
ignoring unspecified arguments.
139
139
140
140
Returns:
141
- A stub to configure using `then_return`, `then_raise`, `then_do`, or
142
- `then_enter_with`.
141
+ A stub to configure using [`then_return`][decoy.Stub.then_return],
142
+ [`then_raise`][decoy.Stub.then_raise], [`then_do`][decoy.Stub.then_do],
143
+ or [`then_enter_with`][decoy.Stub.then_enter_with].
143
144
144
145
Example:
145
146
```python
@@ -202,12 +203,27 @@ def test_create_something(decoy: Decoy):
202
203
ignore_extra_args = ignore_extra_args ,
203
204
)
204
205
206
+ def prop (self , _rehearsal_result : ReturnT ) -> "Prop[ReturnT]" :
207
+ """Create property setter and deleter rehearsals.
208
+
209
+ See [property mocking guide](../advanced/properties/) for more details.
210
+
211
+ Arguments:
212
+ _rehearsal_result: The property to mock, for typechecking.
213
+
214
+ Returns:
215
+ A prop rehearser on which you can call [`set`][decoy.Prop.set] or
216
+ [`delete`][decoy.Prop.delete] to create property rehearsals.
217
+ """
218
+ prop_core = self ._core .prop (_rehearsal_result )
219
+ return Prop (core = prop_core )
220
+
205
221
def reset (self ) -> None :
206
222
"""Reset all mock state.
207
223
208
224
This method should be called after every test to ensure spies and stubs
209
- don't leak between tests. The `decoy` fixture provided by the pytest plugin
210
- will call `reset` automatically.
225
+ don't leak between tests. The [ `decoy`][decoy.pytest_plugin.decoy] fixture
226
+ provided by the pytest plugin will call `reset` automatically.
211
227
212
228
The `reset` method may also trigger warnings if Decoy detects any questionable
213
229
mock usage. See [decoy.warnings][] for more details.
@@ -243,7 +259,8 @@ def then_raise(self, error: Exception) -> None:
243
259
Note:
244
260
Setting a stub to raise will prevent you from writing new
245
261
rehearsals, because they will raise. If you need to make more calls
246
- to `when`, you'll need to wrap your rehearsal in a `try`.
262
+ to [`when`][decoy.Decoy.when], you'll need to wrap your rehearsal
263
+ in a `try`.
247
264
"""
248
265
self ._core .then_raise (error )
249
266
@@ -299,4 +316,50 @@ def then_enter_with(
299
316
self ._core .then_enter_with (value )
300
317
301
318
302
- __all__ = ["Decoy" , "Stub" , "matchers" , "warnings" , "errors" ]
319
+ class Prop (Generic [ReturnT ]):
320
+ """Rehearsal creator for mocking property setters and deleters.
321
+
322
+ See [property mocking guide](../advanced/properties/) for more details.
323
+ """
324
+
325
+ def __init__ (self , core : PropCore ) -> None :
326
+ self ._core = core
327
+
328
+ def set (self , value : ReturnT ) -> None :
329
+ """Create a property setter rehearsal.
330
+
331
+ By wrapping `set` in a call to [`when`][decoy.Decoy.when] or
332
+ [`verify`][decoy.Decoy.verify], you can stub or verify a call
333
+ to a property setter.
334
+
335
+ Arguments:
336
+ value: The value
337
+
338
+ Example:
339
+ ```python
340
+ some_obj = decoy.mock()
341
+ some_obj.prop = 42
342
+ decoy.verify(decoy.prop(some_obj.prop).set(42))
343
+ ```
344
+ """
345
+ self ._core .set (value )
346
+
347
+ def delete (self ) -> None :
348
+ """Create a property deleter rehearsal.
349
+
350
+ By wrapping `delete` in a call to [`when`][decoy.Decoy.when] or
351
+ [`verify`][decoy.Decoy.verify], you can stub or verify a call
352
+ to a property deleter.
353
+
354
+
355
+ Example:
356
+ ```python
357
+ some_obj = decoy.mock()
358
+ del some_obj.prop
359
+ decoy.verify(decoy.prop(some_obj.prop).delete())
360
+ ```
361
+ """
362
+ self ._core .delete ()
363
+
364
+
365
+ __all__ = ["Decoy" , "Stub" , "Prop" , "matchers" , "warnings" , "errors" ]
0 commit comments