sorenisanerd / mock

Automatically exported from code.google.com/p/mock
BSD 2-Clause "Simplified" License
0 stars 0 forks source link

stopall does not always stop all patches to single target #226

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?

python code to reproduce error

import mock

def myfunc():
    return 'hello'

m = mock.patch('__main__.myfunc').start()
m.return_value = 'firstmock'
myfunc()

m2 = mock.patch('__main__.myfunc').start()
m2.return_value = 'secondmock'
myfunc()

mock.patch.stopall()
myfunc()

What is the expected output? What do you see instead?
I would expect the output from above to be:
'firstmock'
'secondmock'
'hello'

Instead, sometimes it comes out as:
'firstmock'
'secondmock'
'firstmock'

This result is non-deterministic though so it may also come out as expected. 
Re-run several times to get the error. 

This is a result of using a set to store the active patches. Conversion from a 
set to a list is non-deterministic because the set has no notion of order. 

Please provide any additional information below.

This use case may seem strange, but it shows up in large unit tests where a 
base class sets up a default patch to catch external calls or something similar 
and then an individual unit test requiring specific mock behavior patches it 
differently. 

I have a patch here that fixes the problem using a list to store the patches to 
maintain order and call them in reverse order to stop them in the correct order.

https://code.google.com/r/blak111-mockfix/source/detail?r=3c2f72b0253075d628afb3
33a79b7cb118132294

Original issue reported on code.google.com by blak...@gmail.com on 13 Apr 2014 at 5:46

GoogleCodeExporter commented 9 years ago
Thanks for the report. Note that I've reported this on the unittest.mock bug 
tracker too: http://bugs.python.org/issue21239

Original comment by fuzzyman on 15 Apr 2014 at 3:56