Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

patch abnormalities #121

Closed
ja8zyjits opened this issue Apr 26, 2019 · 3 comments
Closed

patch abnormalities #121

ja8zyjits opened this issue Apr 26, 2019 · 3 comments

Comments

@ja8zyjits
Copy link

ja8zyjits commented Apr 26, 2019

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?
@Martiusweb
Copy link
Owner

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.

@ja8zyjits
Copy link
Author

@Martiusweb Thanks for your prompt response.

@Martiusweb
Copy link
Owner

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants