Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
3667e1ee
Commit
3667e1ee
authored
Sep 29, 2019
by
Lisa Roach
Committed by
GitHub
Sep 29, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-38163: Child mocks detect their type as sync or async (GH-16471)
parent
5bcc6d89
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
76 additions
and
28 deletions
+76
-28
Doc/library/unittest.mock.rst
Doc/library/unittest.mock.rst
+27
-1
Lib/unittest/mock.py
Lib/unittest/mock.py
+3
-2
Lib/unittest/test/testmock/testasync.py
Lib/unittest/test/testmock/testasync.py
+42
-25
Misc/NEWS.d/next/Library/2019-09-28-20-16-40.bpo-38163.x51-vK.rst
...S.d/next/Library/2019-09-28-20-16-40.bpo-38163.x51-vK.rst
+4
-0
No files found.
Doc/library/unittest.mock.rst
View file @
3667e1ee
...
...
@@ -865,7 +865,7 @@ object::
True
The result of ``mock()`` is an async function which will have the outcome
of ``side_effect`` or ``return_value``:
of ``side_effect`` or ``return_value``
after it has been awaited
:
- if ``side_effect`` is a function, the async function will return the
result of that function,
...
...
@@ -890,6 +890,32 @@ object::
>>> mock() # doctest: +SKIP
<coroutine object AsyncMockMixin._mock_call at ...>
Setting the *spec* of a :class:`Mock`, :class:`MagicMock`, or :class:`AsyncMock`
to a class with asynchronous and synchronous functions will automatically
detect the synchronous functions and set them as :class:`MagicMock` (if the
parent mock is :class:`AsyncMock` or :class:`MagicMock`) or :class:`Mock` (if
the parent mock is :class:`Mock`). All asynchronous functions will be
:class:`AsyncMock`.
>>> class ExampleClass:
... def sync_foo():
... pass
... async def async_foo():
... pass
...
>>> a_mock = AsyncMock(ExampleClass)
>>> a_mock.sync_foo
<MagicMock name='mock.sync_foo' id='...'>
>>> a_mock.async_foo
<AsyncMock name='mock.async_foo' id='...'>
>>> mock = Mock(ExampleClass)
>>> mock.sync_foo
<Mock name='mock.sync_foo' id='...'>
>>> mock.async_foo
<AsyncMock name='mock.async_foo' id='...'>
.. method:: assert_awaited()
Assert that the mock was awaited at least once. Note that this is separate
...
...
Lib/unittest/mock.py
View file @
3667e1ee
...
...
@@ -992,8 +992,9 @@ class NonCallableMock(Base):
# Any asynchronous magic becomes an AsyncMock
klass
=
AsyncMock
elif
issubclass
(
_type
,
AsyncMockMixin
):
if
_new_name
in
_all_sync_magics
:
# Any synchronous magic becomes a MagicMock
if
(
_new_name
in
_all_sync_magics
or
self
.
_mock_methods
and
_new_name
in
self
.
_mock_methods
):
# Any synchronous method on AsyncMock becomes a MagicMock
klass
=
MagicMock
else
:
klass
=
AsyncMock
...
...
Lib/unittest/test/testmock/testasync.py
View file @
3667e1ee
...
...
@@ -3,7 +3,7 @@ import inspect
import
re
import
unittest
from
unittest.mock
import
(
ANY
,
call
,
AsyncMock
,
patch
,
MagicMock
,
from
unittest.mock
import
(
ANY
,
call
,
AsyncMock
,
patch
,
MagicMock
,
Mock
,
create_autospec
,
sentinel
,
_CallList
)
...
...
@@ -232,33 +232,50 @@ class AsyncAutospecTest(unittest.TestCase):
class
AsyncSpecTest
(
unittest
.
TestCase
):
def
test_spec_as_async_positional_magicmock
(
self
):
mock
=
MagicMock
(
async_func
)
self
.
assertIsInstance
(
mock
,
MagicMock
)
m
=
mock
()
self
.
assertTrue
(
inspect
.
isawaitable
(
m
))
asyncio
.
run
(
m
)
def
test_spec_normal_methods_on_class
(
self
):
def
inner_test
(
mock_type
):
mock
=
mock_type
(
AsyncClass
)
self
.
assertIsInstance
(
mock
.
async_method
,
AsyncMock
)
self
.
assertIsInstance
(
mock
.
normal_method
,
MagicMock
)
def
test_spec_as_async_kw_magicmock
(
self
):
mock
=
MagicMock
(
spec
=
async_func
)
self
.
assertIsInstance
(
mock
,
MagicMock
)
m
=
mock
()
self
.
assertTrue
(
inspect
.
isawaitable
(
m
))
asyncio
.
run
(
m
)
for
mock_type
in
[
AsyncMock
,
MagicMock
]:
with
self
.
subTest
(
f"test method types with
{
mock_type
}
"
):
inner_test
(
mock_type
)
def
test_spec_as_async_kw_AsyncMock
(
self
):
mock
=
AsyncMock
(
spec
=
async_func
)
self
.
assertIsInstance
(
mock
,
AsyncMock
)
m
=
mock
()
self
.
assertTrue
(
inspect
.
isawaitable
(
m
))
asyncio
.
run
(
m
)
def
test_spec_normal_methods_on_class_with_mock
(
self
):
mock
=
Mock
(
AsyncClass
)
self
.
assertIsInstance
(
mock
.
async_method
,
AsyncMock
)
self
.
assertIsInstance
(
mock
.
normal_method
,
Mock
)
def
test_spec_as_async_positional_AsyncMock
(
self
):
mock
=
AsyncMock
(
async_func
)
self
.
assertIsInstance
(
mock
,
AsyncMock
)
m
=
mock
()
self
.
assertTrue
(
inspect
.
isawaitable
(
m
))
asyncio
.
run
(
m
)
def
test_spec_mock_type_kw
(
self
):
def
inner_test
(
mock_type
):
async_mock
=
mock_type
(
spec
=
async_func
)
self
.
assertIsInstance
(
async_mock
,
mock_type
)
with
self
.
assertWarns
(
RuntimeWarning
):
# Will raise a warning because never awaited
self
.
assertTrue
(
inspect
.
isawaitable
(
async_mock
()))
sync_mock
=
mock_type
(
spec
=
normal_func
)
self
.
assertIsInstance
(
sync_mock
,
mock_type
)
for
mock_type
in
[
AsyncMock
,
MagicMock
,
Mock
]:
with
self
.
subTest
(
f"test spec kwarg with
{
mock_type
}
"
):
inner_test
(
mock_type
)
def
test_spec_mock_type_positional
(
self
):
def
inner_test
(
mock_type
):
async_mock
=
mock_type
(
async_func
)
self
.
assertIsInstance
(
async_mock
,
mock_type
)
with
self
.
assertWarns
(
RuntimeWarning
):
# Will raise a warning because never awaited
self
.
assertTrue
(
inspect
.
isawaitable
(
async_mock
()))
sync_mock
=
mock_type
(
normal_func
)
self
.
assertIsInstance
(
sync_mock
,
mock_type
)
for
mock_type
in
[
AsyncMock
,
MagicMock
,
Mock
]:
with
self
.
subTest
(
f"test spec positional with
{
mock_type
}
"
):
inner_test
(
mock_type
)
def
test_spec_as_normal_kw_AsyncMock
(
self
):
mock
=
AsyncMock
(
spec
=
normal_func
)
...
...
Misc/NEWS.d/next/Library/2019-09-28-20-16-40.bpo-38163.x51-vK.rst
0 → 100644
View file @
3667e1ee
Child mocks will now detect their type as either synchronous or
asynchronous, asynchronous child mocks will be AsyncMocks and synchronous
child mocks will be either MagicMock or Mock (depending on their parent
type).
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment