patch abnormalities
ja8zyjits opened this issue · 3 comments
The problem
while patching and sub classing there seems to be a deviation from the normal unittests behaviour.
scritp.py
def run_something():
pass
test_script.py
import asynctest
import asyncio
import unittest
import script
class MainTest(asynctest.TestCase):
def setUp(self):
pass
@asynctest.patch("script.run_something")
async def test_main(self, mock_run):
script.run_something()
self.assertEqual(mock_run.call_count, 1)
class MainTest2(MainTest):
def setUp(self):
pass
if __name__=="__main__":
unittest.main()
while running the code with python -m unittest
iam gettting the following error
.F
======================================================================
FAIL: test_main (test_script.MainTest2)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/jzy/work/asynctest_issue_virtual/lib/python3.6/site-packages/asynctest/case.py", line 297, in run
self._run_test_method(testMethod)
File "/home/jzy/work/asynctest_issue_virtual/lib/python3.6/site-packages/asynctest/case.py", line 354, in _run_test_method
self.loop.run_until_complete(result)
File "/home/jzy/work/asynctest_issue_virtual/lib/python3.6/site-packages/asynctest/case.py", line 224, in wrapper
return method(*args, **kwargs)
File "/usr/lib/python3.6/asyncio/base_events.py", line 473, in run_until_complete
return future.result()
File "/home/jzy/work/asynctest_issue_virtual/lib/python3.6/site-packages/asynctest/_awaitable.py", line 21, in wrapper
return await coroutine(*args, **kwargs)
File "/home/jzy/work/asynctest_issue_virtual/lib/python3.6/site-packages/asynctest/mock.py", line 1006, in __next__
return self.gen.send(None)
File "/home/jzy/work/asynctest_issue_virtual/scripts/test_script.py", line 13, in test_main
self.assertEqual(mock_run.call_count, 1)
AssertionError: 2 != 1
----------------------------------------------------------------------
Ran 2 tests in 0.002s
FAILED (failures=1)
But the same code in unittest passes.
test_script.py
import asynctest
import asyncio
import unittest
import script
class MainTest(asynctest.TestCase):
def setUp(self):
pass
@unittest.mock.patch("script.run_something")
def test_main(self, mock_run):
script.run_something()
self.assertEqual(mock_run.call_count, 1)
class MainTest2(MainTest):
def setUp(self):
pass
if __name__=="__main__":
unittest.main()
while running the code with python -m unittest
iam gettting the following output
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
The workaround
Iam able to get around this issue by using the context managers instead of the decorators like
with asynctest.patch("script.run_something") as mock_something:
And the test succeeds
Support information
- python version
3.6.7
- asynctest version
Name: asynctest
Version: 0.12.4
Summary: Enhance the standard unittest package with features for testing asyncio libraries
Home-page: https://github.com/Martiusweb/asynctest/
Author: Martin Richard
Author-email: martius@martiusweb.net
License: Apache 2
Location: /home/jzy/work/asynctest_issue_virtual/lib/python3.6/site-packages
The question
- Is this an intended behavior?
Hi,
Thanks for your report.
You're running the same decorated test method twice, and it re-uses the same mock object, which is indeed a bug since unittest issues a new mock object every time.
I'll work on it.
@Martiusweb Thanks for your prompt response.
In fact, this issue raises other problems happening with concurrent executions of patched coroutines.
In particular, since several coroutines instances can live simultaneously, several instances of a patched coroutine will break each other.
The issue is not about re-using the same mock, but using the same patch for each coroutine instance. I'm not sure yet how to solve this: should the patchings be tied to the coroutine instance instead of the coroutine function?
The internal behavior of asynctest will likely change quite a lot, so I think it should not be released in a patch version. I'll merge the deprecation of python 3.4 first.