API Reference#
decoy.Decoy
#
Decoy mock factory and state container.
You should create a new Decoy instance before each test and call
reset
after each test. If you use the
decoy
pytest fixture, this is done
automatically. See the setup guide for more details.
Example
decoy = Decoy()
# test your subject
...
decoy.reset()
decoy.Decoy.mock(*, cls=None, func=None, name=None, is_async=False)
#
Create a mock. See the mock creation guide for more details.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
cls |
Optional[Any]
|
A class definition that the mock should imitate. |
None
|
func |
Optional[Any]
|
A function definition the mock should imitate. |
None
|
name |
Optional[str]
|
A name to use for the mock. If you do not use
|
None
|
is_async |
bool
|
Force the returned spy to be asynchronous. This argument
only applies if you don't use |
False
|
Returns:
Type | Description |
---|---|
Any
|
A spy typecast as the object it's imitating, if any. |
Example
def test_get_something(decoy: Decoy):
db = decoy.mock(cls=Database)
# ...
decoy.Decoy.prop(_rehearsal_result)
#
Create property setter and deleter rehearsals.
See property mocking guide for more details.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
_rehearsal_result |
ReturnT
|
The property to mock, for typechecking. |
required |
Returns:
Type | Description |
---|---|
Prop[ReturnT]
|
A prop rehearser on which you can call |
Prop[ReturnT]
|
|
decoy.Decoy.reset()
#
Reset all mock state.
This method should be called after every test to ensure spies and stubs
don't leak between tests. The decoy
fixture
provided by the pytest plugin will call reset
automatically.
The reset
method may also trigger warnings if Decoy detects any questionable
mock usage. See decoy.warnings for more details.
decoy.Decoy.verify(*_rehearsal_results, times=None, ignore_extra_args=False)
#
Verify a mock was called using one or more rehearsals.
See verification usage guide for more details.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
_rehearsal_results |
Any
|
The return value of rehearsals, unused except to determine how many rehearsals to verify. |
()
|
times |
Optional[int]
|
How many times the call should appear. If |
None
|
ignore_extra_args |
bool
|
Allow the rehearsal to specify fewer arguments than the actual call. Decoy will compare and match any given arguments, ignoring unspecified arguments. |
False
|
Raises:
Type | Description |
---|---|
VerifyError
|
The verification was not satisfied. |
Example
def test_create_something(decoy: Decoy):
gen_id = decoy.mock(func=generate_unique_id)
# ...
decoy.verify(gen_id("model-prefix_"))
Note
A "rehearsal" is an actual call to the test fake. The fact that
the call is written inside verify
is purely for typechecking and
API sugar. Decoy will pop the last call(s) to any fake off its
call stack, which will end up being the call inside verify
.
decoy.Decoy.when(_rehearsal_result, *, ignore_extra_args=False)
#
Create a Stub
configuration using a rehearsal call.
See stubbing usage guide for more details.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
_rehearsal_result |
ReturnT
|
The return value of a rehearsal, used for typechecking. |
required |
ignore_extra_args |
bool
|
Allow the rehearsal to specify fewer arguments than the actual call. Decoy will compare and match any given arguments, ignoring unspecified arguments. |
False
|
Returns:
Type | Description |
---|---|
Stub[ReturnT]
|
A stub to configure using |
Stub[ReturnT]
|
|
Stub[ReturnT]
|
or |
Example
db = decoy.mock(cls=Database)
decoy.when(db.exists("some-id")).then_return(True)
Note
The "rehearsal" is an actual call to the test fake. Because the
call is written inside when
, Decoy is able to infer that the call
is a rehearsal for stub configuration purposes rather than a call
from the code-under-test.
decoy.Stub
#
Bases: Generic[ReturnT]
A rehearsed Stub that can be used to configure mock behaviors.
See stubbing usage guide for more details.
decoy.Stub.then_do(action)
#
Configure the stub to trigger an action.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
action |
Callable[..., Union[ReturnT, Coroutine[Any, Any, ReturnT]]]
|
The function to call. Called with whatever arguments
are actually passed to the stub. May be an |
required |
Raises:
Type | Description |
---|---|
MockNotAsyncError
|
|
decoy.Stub.then_enter_with(value)
#
Configure the stub to return a value wrapped in a context manager.
The wrapping context manager is compatible with both the synchronous and asynchronous context manager interfaces.
See the context manager usage guide for more details.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
ContextValueT
|
A return value to wrap in a ContextManager. |
required |
decoy.Stub.then_raise(error)
#
Configure the stub to raise an error.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
error |
Exception
|
The error to raise. |
required |
Note
Setting a stub to raise will prevent you from writing new
rehearsals, because they will raise. If you need to make more calls
to when
, you'll need to wrap your rehearsal
in a try
.
decoy.Stub.then_return(*values)
#
Configure the stub to return value(s).
Parameters:
Name | Type | Description | Default |
---|---|---|---|
*values |
ReturnT
|
Zero or more return values. Multiple values will result in different return values for subsequent calls, with the last value latching in once all other values have returned. |
()
|
decoy.Prop
#
Bases: Generic[ReturnT]
Rehearsal creator for mocking property setters and deleters.
See property mocking guide for more details.
decoy.Prop.delete()
#
decoy.Prop.set(value)
#
Create a property setter rehearsal.
By wrapping set
in a call to when
or
verify
, you can stub or verify a call
to a property setter.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
ReturnT
|
The value |
required |
Example
some_obj = decoy.mock()
some_obj.prop = 42
decoy.verify(decoy.prop(some_obj.prop).set(42))
decoy.matchers
#
Matcher helpers.
A "matcher" is a class with an __eq__
method defined. Use them anywhere
in your test where you would use an actual value for equality (==
) comparison.
Matchers help you loosen assertions where strict adherence to an exact value is not relevant to what you're trying to test. See the matchers guide for more details.
Example
from decoy import Decoy, matchers
# ...
def test_logger_called(decoy: Decoy):
# ...
decoy.verify(
logger.log(msg=matchers.StringMatching("hello"))
)
Note
Identity comparisons (is
) will not work with matchers. Decoy only uses
equality comparisons (==
) for stubbing and verification.
decoy.matchers.Anything()
#
Match anything except None.
Example
assert "foobar" == Anything()
assert None != Anything()
decoy.matchers.Captor()
#
Match anything, capturing its value.
The last captured value will be set to captor.value
. All captured
values will be placed in the captor.values
list, which can be
helpful if a captor needs to be triggered multiple times.
Example
captor = Captor()
assert "foobar" == captor
print(captor.value) # "foobar"
print(captor.values) # ["foobar"]
decoy.matchers.DictMatching(values)
#
Match any dictionary with the passed in keys / values.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
values |
Mapping[str, Any]
|
Keys and values to check. |
required |
Example
value = {"hello": "world", "goodbye": "so long"}
assert value == matchers.DictMatching({"hello": "world"})
decoy.matchers.ErrorMatching(error, match=None)
#
Match any error matching an Exception type and optional message matcher.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
error |
Type[ErrorT]
|
Exception type to match against. |
required |
match |
Optional[str]
|
Pattern to check against; will be compiled into an re.Pattern. |
None
|
Example
assert ValueError("oh no!") == ErrorMatching(ValueError)
assert ValueError("oh no!") == ErrorMatching(ValueError, match="no")
decoy.matchers.HasAttributes(attributes)
#
Match anything with the passed in attributes.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
attributes |
Mapping[str, Any]
|
Attribute values to check. |
required |
Example
@dataclass
class HelloWorld:
hello: str = "world"
goodby: str = "so long"
assert HelloWorld() == matchers.HasAttributes({"hello": "world"})
decoy.matchers.IsA(match_type, attributes=None)
#
Match anything that satisfies the passed in type.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
match_type |
type
|
Type to match. |
required |
attributes |
Optional[Mapping[str, Any]]
|
Optional set of attributes to match |
None
|
Example
assert "foobar" == IsA(str)
assert datetime.now() == IsA(datetime)
assert 42 == IsA(int)
@dataclass
class HelloWorld:
hello: str = "world"
goodby: str = "so long"
assert HelloWorld() == IsA(HelloWorld, {"hello": "world"})
decoy.matchers.IsNot(value)
#
Match anything that isn't the passed in value.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
object
|
Value to check against. |
required |
Example
assert "foobar" == IsNot("bazquux")
assert 42 == IsNot("the question")
assert 1 != IsNot(1)
decoy.matchers.StringMatching(match)
#
Match any string matching the passed in pattern.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
match |
str
|
Pattern to check against; will be compiled into an re.Pattern. |
required |
Example
assert "foobar" == StringMatching("bar")
assert "foobar" != StringMatching("^bar")
decoy.errors
#
Errors raised by Decoy.
See the errors guide for more details.
decoy.errors.MissingRehearsalError
#
Bases: ValueError
An error raised when a Decoy method is called without rehearsal(s).
This error is raised if you use when
,
verify
, or prop
incorrectly
in your tests. When using async/await, this error can be triggered if you
forget to include await
with your rehearsal.
See the MissingRehearsalError guide for more details.
decoy.errors.MockNameRequiredError
#
Bases: ValueError
An error raised if a name is not provided for a mock.
See the MockNameRequiredError guide for more details.
decoy.errors.MockNotAsyncError
#
Bases: TypeError
An error raised when an asynchronous function is used with a synchronous mock.
This error is raised if you pass an async def
function
to a synchronous stub's then_do
method.
See the MockNotAsyncError guide for more details.
decoy.errors.VerifyError
#
Bases: AssertionError
An error raised when actual calls do not match rehearsals given to verify
.
See spying with verify for more details.
Attributes:
Name | Type | Description |
---|---|---|
rehearsals |
Sequence[VerifyRehearsal]
|
Rehearsals that were being verified. |
calls |
Sequence[SpyEvent]
|
Actual calls to the mock(s). |
times |
Optional[int]
|
The expected number of calls to the mock, if any. |
decoy.warnings
#
Warnings raised by Decoy.
See the warnings guide for more details.
decoy.warnings.DecoyWarning
#
Bases: UserWarning
Base class for Decoy warnings.
decoy.warnings.IncorrectCallWarning
#
Bases: DecoyWarning
A warning raised if a Decoy mock with a spec is called incorrectly.
If a call to a Decoy mock is incorrect according to inspect.signature
,
this warning will be raised.
See the IncorrectCallWarning guide for more details.
decoy.warnings.MiscalledStubWarning
#
Bases: DecoyWarning
A warning when a configured Stub is called with non-matching arguments.
This warning is raised if a mock is both:
- Configured as a stub with
when
- Called with arguments that do not match any configured behaviors
See the MiscalledStubWarning guide for more details.
Attributes:
Name | Type | Description |
---|---|---|
rehearsals |
Sequence[SpyRehearsal]
|
The mocks's configured rehearsals. |
calls |
Sequence[SpyEvent]
|
Actual calls to the mock. |
decoy.warnings.MissingSpecAttributeWarning
#
Bases: DecoyWarning
A warning raised if a Decoy mock with a spec is used with a missing attribute.
This will become an error in the next major version of Decoy. See the MissingSpecAttributeWarning guide for more details.
decoy.warnings.RedundantVerifyWarning
#
Bases: DecoyWarning
A warning when a mock is redundantly checked with verify
.
A verify
assertion is redundant if:
See the RedundantVerifyWarning guide for more details.
decoy.pytest_plugin
#
Pytest plugin to setup and teardown a Decoy instance.
The plugin will be registered with pytest when you install Decoy. It adds a fixture without modifying any other pytest behavior. Its usage is optional but highly recommended.
decoy.pytest_plugin.decoy()
#
Get a decoy.Decoy container and reset it after the test.
This function is function-scoped pytest fixture that will be automatically inserted by the plugin.
Example
def test_my_thing(decoy: Decoy) -> None:
my_fake_func = decoy.mock()
# ...