Skip to content

Commit

Permalink
Set name to unittest mocks
Browse files Browse the repository at this point in the history
- Closes #16
  • Loading branch information
ollipa committed Feb 7, 2022
1 parent a7656dc commit f092534
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 109 deletions.
39 changes: 29 additions & 10 deletions src/chainmock/_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ def __init__(
self,
parent: Mock,
attr_mock: AnyMock,
name: str,
*,
kind: Literal["spy", "mock"] = "mock",
patch: Optional[umock._patch[Any]] = None, # pylint: disable=unsubscriptable-object
Expand All @@ -65,7 +64,6 @@ def __init__(
)
self.__parent = parent
self._attr_mock = attr_mock
self.__name = name
self.__assertions: List[Callable[..., None]] = []
self.__patch = patch
self._kind = kind
Expand Down Expand Up @@ -1072,8 +1070,9 @@ def _assert_call_count(
if modifier == "at most" and self._attr_mock.call_count <= call_count:
return
modifier_str = f"{modifier} " if modifier else ""
name = self._attr_mock._mock_name or "mock" # pylint:disable=protected-access
msg = (
f"Expected '{self.__name}' to have been called {modifier_str}" # pylint:disable=protected-access
f"Expected '{name}' to have been called {modifier_str}" # pylint:disable=protected-access
f"{self._format_call_count(call_count)}. "
f"Called {self._format_call_count(self._attr_mock.call_count)}."
f"{self._attr_mock._calls_repr()}"
Expand All @@ -1090,8 +1089,9 @@ def _assert_await_count(
if modifier == "at most" and self._attr_mock.await_count <= await_count:
return
modifier_str = f"{modifier} " if modifier else ""
name = self._attr_mock._mock_name or "mock" # pylint:disable=protected-access
msg = (
f"Expected '{self.__name}' to have been awaited {modifier_str}"
f"Expected '{name}' to have been awaited {modifier_str}"
f"{self._format_call_count(await_count)}. "
f"Awaited {self._format_call_count(self._attr_mock.await_count)}."
f"{self._awaits_repr()}"
Expand Down Expand Up @@ -1375,7 +1375,7 @@ def spy(self, name: str) -> Assert:
return cached
parsed_name = self.__remove_name_mangling(name)
original = getattr(self.__target, parsed_name)
attr_mock = umock.MagicMock(name=parsed_name)
attr_mock = umock.MagicMock(name=self.__format_mock_name(name))
parameters = tuple(inspect.signature(original).parameters.keys())
is_class_method = self.__get_method_type(parsed_name, classmethod)
is_static_method = self.__get_method_type(parsed_name, staticmethod)
Expand All @@ -1394,7 +1394,7 @@ def pass_through(*args: Any, **kwargs: Any) -> Any:
patch = umock.patch.object(self.__target, parsed_name, new=pass_through)
patch.start()
self.__object_patches.append(patch)
assertion = Assert(self, attr_mock, parsed_name, kind="spy", _internal=True)
assertion = Assert(self, attr_mock, kind="spy", _internal=True)
self.__assertions[name] = assertion
return assertion

Expand Down Expand Up @@ -1553,7 +1553,8 @@ def __stub_attribute(
force_property=force_property if not parts else False,
force_async=force_async if not parts else False,
)
assertion = Assert(self, attr_mock, name, _internal=True)
attr_mock._mock_name = f"Stub.{name}" # pylint: disable=protected-access
assertion = Assert(self, attr_mock, _internal=True)
if len(parts) > 0:
# Support for chaining methods
assertion.return_value(self)
Expand Down Expand Up @@ -1613,7 +1614,7 @@ def __patch_attribute(
force_property=False,
force_async=force_async if not parts else False,
)
assertion = Assert(self, attr_mock, name, _internal=True)
assertion = Assert(self, attr_mock, _internal=True)
if len(parts) > 0:
# Support for chaining methods
Stub = type("Stub", (Mock,), {}) # Use intermediary class to attach properties
Expand Down Expand Up @@ -1684,11 +1685,15 @@ def __mock_attribute(
elif not parts and force_async:
new_callable = umock.AsyncMock
patch = umock.patch.object(
self.__target, name, new_callable=new_callable, create=create
self.__target,
name,
new_callable=new_callable,
create=create,
name=self.__format_mock_name(name),
)
attr_mock = patch.start()
self.__object_patches.append(patch)
assertion = Assert(self, attr_mock, name, patch=patch, _internal=True)
assertion = Assert(self, attr_mock, patch=patch, _internal=True)
if len(parts) > 0:
# Support for chaining methods
Stub = type("Stub", (Mock,), {}) # Use intermediary class to attach properties
Expand All @@ -1701,6 +1706,20 @@ def __mock_attribute(
)
return assertion

def __format_mock_name(self, name: str) -> str:
if self.__target is None:
return name
target = self.__target
if (
not inspect.isclass(target)
and not inspect.ismodule(target)
and hasattr(target, "__class__")
):
target = target.__class__
if hasattr(target, "__name__"):
return f"{target.__name__}.{name}"
return name

def _reset(self) -> None:
while len(self.__object_patches) > 0:
patch = self.__object_patches.pop()
Expand Down
28 changes: 14 additions & 14 deletions tests/test_async_mocking.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ async def method(self, arg1: str, arg2: int = 10) -> str:
AssertionError,
(
"expected await not found.\n"
"Expected: method('foo', arg2=5)\n"
"Actual: method('foo', arg2=10)"
"Expected: FooClass.method('foo', arg2=5)\n"
"Actual: FooClass.method('foo', arg2=10)"
),
):
State.teardown()
Expand All @@ -76,8 +76,8 @@ async def method(self, arg1: str, arg2: int = 10) -> str:
AssertionError,
(
"expected await not found.\n"
"Expected: method('foo', arg2=5)\n"
"Actual: method('bar', arg2=5)"
"Expected: FooClass.method('foo', arg2=5)\n"
"Actual: FooClass.method('bar', arg2=5)"
),
):
State.teardown()
Expand All @@ -87,7 +87,7 @@ async def method(self, arg1: str, arg2: int = 10) -> str:
await FooClass().method("foo", arg2=5)
with assert_raises(
AssertionError,
"Expected method to have been awaited once. Awaited 2 times.",
"Expected FooClass.method to have been awaited once. Awaited 2 times.",
):
State.teardown()

Expand All @@ -108,7 +108,7 @@ async def method(self, arg1: str, arg2: int = 10) -> str:
await FooClass().method("baz", arg2=3)
with assert_raises(
AssertionError,
"method('foo', arg2=4) await not found",
"FooClass.method('foo', arg2=4) await not found",
):
State.teardown()

Expand Down Expand Up @@ -358,7 +358,7 @@ async def method(self) -> None:
await FooClass().method()
with assert_raises(
AssertionError,
"Expected method to not have been awaited. Awaited 1 times.",
"Expected FooClass.method to not have been awaited. Awaited 1 times.",
):
State.teardown()

Expand All @@ -373,7 +373,7 @@ async def method(self) -> None:
State.teardown()

mocker(FooClass).mock("method").awaited()
with assert_raises(AssertionError, "Expected method to have been awaited."):
with assert_raises(AssertionError, "Expected FooClass.method to have been awaited."):
State.teardown()

async def test_mock_async_instance_method_awaited_once(self) -> None:
Expand All @@ -387,7 +387,7 @@ async def method(self) -> None:

mocker(FooClass).mock("method").awaited_once()
with assert_raises(
AssertionError, "Expected 'method' to have been awaited once. Awaited 0 times."
AssertionError, "Expected 'FooClass.method' to have been awaited once. Awaited 0 times."
):
State.teardown()

Expand All @@ -405,7 +405,7 @@ async def method(self) -> None:
await FooClass().method()
with assert_raises(
AssertionError,
"Expected 'method' to have been awaited twice. Awaited once.\nAwaits: [call()].",
"Expected 'FooClass.method' to have been awaited twice. Awaited once.\nAwaits: [call()].",
):
State.teardown()

Expand All @@ -432,7 +432,7 @@ async def method(self) -> None:
await FooClass().method()
with assert_raises(
AssertionError,
"Expected 'method' to have been awaited 3 times. "
"Expected 'FooClass.method' to have been awaited 3 times. "
"Awaited twice.\nAwaits: [call(), call()].",
):
State.teardown()
Expand All @@ -454,7 +454,7 @@ async def method(self) -> None:
await FooClass().method()
with assert_raises(
AssertionError,
"Expected 'method' to have been awaited at least 3 times. "
"Expected 'FooClass.method' to have been awaited at least 3 times. "
"Awaited twice.\nAwaits: [call(), call()].",
):
State.teardown()
Expand All @@ -465,7 +465,7 @@ async def method(self) -> None:
await FooClass().method()
with assert_raises(
AssertionError,
"Expected 'method' to have been awaited at least 3 times. "
"Expected 'FooClass.method' to have been awaited at least 3 times. "
"Awaited twice.\nAwaits: [call(), call()].",
):
State.teardown()
Expand Down Expand Up @@ -495,7 +495,7 @@ async def method(self) -> None:
await FooClass().method()
with assert_raises(
AssertionError,
"Expected 'method' to have been awaited at most 3 times. "
"Expected 'FooClass.method' to have been awaited at most 3 times. "
"Awaited 4 times.\nAwaits: [call(), call(), call(), call()].",
):
State.teardown()
Expand Down
42 changes: 21 additions & 21 deletions tests/test_async_spying.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ async def test_async_spy_function_called_once_fail(self) -> None:
mocker(common).spy("some_async_function").called_once()
with assert_raises(
AssertionError,
"Expected 'some_async_function' to have been called once. Called 0 times.",
"Expected 'tests.common.some_async_function' to have been called once. Called 0 times.",
):
State.teardown()

Expand All @@ -35,8 +35,8 @@ async def test_async_spy_function_called_once_with_fail(self) -> None:
with assert_raises(
AssertionError,
"expected call not found.\n"
"Expected: some_async_function('foo')\n"
"Actual: some_async_function('bar')",
"Expected: tests.common.some_async_function('foo')\n"
"Actual: tests.common.some_async_function('bar')",
):
State.teardown()

Expand All @@ -50,7 +50,7 @@ async def test_async_spy_class_call_instance_method_called_once_fail(self) -> No
mocker(SomeClass).spy("async_instance_method").called_once()
with assert_raises(
AssertionError,
"Expected 'async_instance_method' to have been called once. Called 0 times.",
"Expected 'SomeClass.async_instance_method' to have been called once. Called 0 times.",
):
State.teardown()

Expand All @@ -66,8 +66,8 @@ async def test_async_spy_class_call_instance_method_called_once_with_fail(self)
with assert_raises(
AssertionError,
"expected call not found.\n"
"Expected: async_instance_method_with_args(1)\n"
"Actual: async_instance_method_with_args(2)",
"Expected: SomeClass.async_instance_method_with_args(1)\n"
"Actual: SomeClass.async_instance_method_with_args(2)",
):
State.teardown()

Expand All @@ -83,7 +83,7 @@ async def test_async_spy_instance_call_instance_method_called_once_fail(self) ->
mocker(instance).spy("async_instance_method").called_once()
with assert_raises(
AssertionError,
"Expected 'async_instance_method' to have been called once. Called 0 times.",
"Expected 'SomeClass.async_instance_method' to have been called once. Called 0 times.",
):
State.teardown()

Expand All @@ -101,8 +101,8 @@ async def test_async_spy_instance_call_instance_method_called_once_with_fail(sel
with assert_raises(
AssertionError,
"expected call not found.\n"
"Expected: async_instance_method_with_args(1)\n"
"Actual: async_instance_method_with_args(2)",
"Expected: SomeClass.async_instance_method_with_args(1)\n"
"Actual: SomeClass.async_instance_method_with_args(2)",
):
State.teardown()

Expand All @@ -116,7 +116,7 @@ async def test_async_spy_class_call_class_method_called_once_fail(self) -> None:
mocker(SomeClass).spy("async_class_method").called_once()
with assert_raises(
AssertionError,
"Expected 'async_class_method' to have been called once. Called 0 times.",
"Expected 'SomeClass.async_class_method' to have been called once. Called 0 times.",
):
State.teardown()

Expand All @@ -132,8 +132,8 @@ async def test_async_spy_class_call_class_method_called_once_with_fail(self) ->
with assert_raises(
AssertionError,
"expected call not found.\n"
"Expected: async_class_method_with_args(2)\n"
"Actual: async_class_method_with_args(3)",
"Expected: SomeClass.async_class_method_with_args(2)\n"
"Actual: SomeClass.async_class_method_with_args(3)",
):
State.teardown()

Expand Down Expand Up @@ -161,7 +161,7 @@ async def test_async_spy_instance_call_class_method_called_once_fail(self) -> No
mocker(instance).spy("async_class_method").called_once()
with assert_raises(
AssertionError,
"Expected 'async_class_method' to have been called once. Called 0 times.",
"Expected 'SomeClass.async_class_method' to have been called once. Called 0 times.",
):
State.teardown()

Expand All @@ -179,8 +179,8 @@ async def test_async_spy_instance_call_class_method_called_once_with_fail(self)
with assert_raises(
AssertionError,
"expected call not found.\n"
"Expected: async_class_method_with_args(2)\n"
"Actual: async_class_method_with_args(3)",
"Expected: SomeClass.async_class_method_with_args(2)\n"
"Actual: SomeClass.async_class_method_with_args(3)",
):
State.teardown()

Expand All @@ -194,7 +194,7 @@ async def test_async_spy_class_call_static_method_called_once_fail(self) -> None
mocker(SomeClass).spy("async_static_method").called_once()
with assert_raises(
AssertionError,
"Expected 'async_static_method' to have been called once. Called 0 times.",
"Expected 'SomeClass.async_static_method' to have been called once. Called 0 times.",
):
State.teardown()

Expand All @@ -210,8 +210,8 @@ async def test_async_spy_class_call_static_method_called_once_with_fail(self) ->
with assert_raises(
AssertionError,
"expected call not found.\n"
"Expected: async_static_method_with_args(3)\n"
"Actual: async_static_method_with_args(4)",
"Expected: SomeClass.async_static_method_with_args(3)\n"
"Actual: SomeClass.async_static_method_with_args(4)",
):
State.teardown()

Expand Down Expand Up @@ -239,7 +239,7 @@ async def test_async_spy_instance_call_static_method_called_once_fail(self) -> N
mocker(instance).spy("async_static_method").called_once()
with assert_raises(
AssertionError,
"Expected 'async_static_method' to have been called once. Called 0 times.",
"Expected 'SomeClass.async_static_method' to have been called once. Called 0 times.",
):
State.teardown()

Expand All @@ -257,7 +257,7 @@ async def test_async_spy_instance_call_static_method_called_once_with_fail(self)
with assert_raises(
AssertionError,
"expected call not found.\n"
"Expected: async_static_method_with_args(3)\n"
"Actual: async_static_method_with_args(4)",
"Expected: SomeClass.async_static_method_with_args(3)\n"
"Actual: SomeClass.async_static_method_with_args(4)",
):
State.teardown()
2 changes: 1 addition & 1 deletion tests/test_chainmock.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def test_init_assert_directly_should_fail(self) -> None:
RuntimeError, "Assert should not be initialized directly. Use mocker function instead."
):
mock = mocker()
Assert(mock, None, "method")
Assert(mock, None)

def test_mocker_should_cache_mocks(self) -> None:
class FooClass:
Expand Down
Loading

0 comments on commit f092534

Please sign in to comment.