Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any way to reset a mocked method to its original state? - Python Mock - mock 1.0b1

I have the following simplified class I'm mocking:

class myClass(object):     @staticmethod     def A():         #...      def check(self):         #code...         value = self.A()         #more code... 

In my first test I mock only the method A

from django.test import TestCase from mock import MagicMock import myClass  class FirstTest(TestCase):  def setUp(self):     myClass.A = MagicMock(return_value = 'CPU')  def test(self):     #some tests      myClassObj = myClass()     myClassObj.check() 

Whereas in my second test I mock the entire check method:

from django.test import TestCase from mock import MagicMock import myClass  class SecondTest(TestCase):  def setUp(self):     myClass.check = MagicMock(return_value = someObject)  def test(self):     #some tests      myClassObj = myClass()     myClassObj.check() 

Now my assertions from my first test fail because, instead of calling check() and mocking A() inside check(), it calls the completely mocked check() from my second test.

Is there any way to clear and set the method to be 'normal' after the test? I tried myClass.check.reset_mock() already, but it doesn't seem to do anything. Moving the order of my tests doesn't do anything either.

I'm using mock 1.0b1 for python from http://pypi.python.org/pypi/mock/

like image 385
SaiyanGirl Avatar asked Jul 31 '12 18:07

SaiyanGirl


People also ask

Should I use mock MagicMock?

Mock vs. MagicMock is a subclass of Mock . It contains all magic methods pre-created and ready to use (e.g. __str__ , __len__ , etc.). Therefore, you should use MagicMock when you need magic methods, and Mock if you don't need them.

How do you mock a function in Python?

How do we mock in Python? Mocking in Python is done by using patch to hijack an API function or object creation call. When patch intercepts a call, it returns a MagicMock object by default. By setting properties on the MagicMock object, you can mock the API call to return any value you want or raise an Exception .

What is side effect in mock python?

side_effect: A function to be called whenever the Mock is called. See the side_effect attribute. Useful for raising exceptions or dynamically changing return values. The function is called with the same arguments as the mock, and unless it returns DEFAULT , the return value of this function is used as the return value.

What is mocking in unit testing Python?

What is mocking in Python? Mocking in Python means the unittest. mock library is being utilized to replace parts of the system with mock objects, allowing easier and more efficient unit testing than would otherwise be possible.


2 Answers

You can use mock.patch as a decorator or a context manager:

from mock import patch, MagicMock  @patch('myClass.A', MagicMock(return_value='CPU')) def test(self):     pass 

or:

def test(self):     with patch('myClass.A', MagicMock(return_value='CPU')):         pass 

If you don't supply a mock object to patch then it will provide an autospecced mock that you can modify:

@patch('myClass.A') def test(self, mock_A):     mock_A.return_value = 'CPU'     pass 

or:

def test(self):     with patch('myClass.A') as mock_A:         mock_A.return_value = 'CPU'         pass 

In all cases the original value will be restored when the decorated test function or context manager finishes.

like image 138
ecatmur Avatar answered Oct 14 '22 22:10

ecatmur


You can stash the function away on self and put it back when you're done.

import unittest  from mock import MagicMock from MyClass import MyClass  class FirstTest(unittest.TestCase):      def setUp(self):         self.A = MyClass.A         MyClass.A = MagicMock(name='mocked A', return_value='CPU')       def tearDown(self):         MyClass.A = self.A      def test_mocked_static_method(self):         print 'First Test'         print MyClass.check         print MyClass.A   class SecondTest(unittest.TestCase):      def setUp(self):         MyClass.check = MagicMock(name='mocked check', return_value=object)      def test_check_mocked_check_method(self):         print 'Second Test'         print MyClass.check         print MyClass.A   if __name__ == '__main__':     unittest.main() 

Running this file gives the following output:

First Test <unbound method MyClass.check>  <MagicMock name='mocked A' id='141382732'> Second Test <MagicMock name='mocked check' id='141382860'> <unbound method MyClass.A> 

I found myself using the patch decorator a lot more than setUp and tearDown now. In this case you could do

from mock import patch  @patch('MyClass.A') def test_mocked_static_method(self, mocked_A)     mocked_A.return_value = 'CPU'     # This mock will expire when the test method is finished 
like image 24
aychedee Avatar answered Oct 14 '22 22:10

aychedee