2018年2月8日 星期四

[ Python 常見問題 ] Mocking a class: Mock() or patch()?

Source From Here 
Question 
I am using mock with Python and was wondering which of those two approaches is better (read: more pythonic). 
Method one: Just create a mock object and use that. The code looks like: 
  1. def test_one (self):  
  2.     mock = Mock()  
  3.     mock.method.return_value = True   
  4.     self.sut.something(mock) # This should called mock.method and checks the result.   
  5.     self.assertTrue(mock.method.called)  
Method two: Use patch to create a mock. The code looks like: 
  1. @patch("MyClass")  
  2. def test_two (self, mock):  
  3.     instance = mock.return_value  
  4.     instance.method.return_value = True  
  5.     self.sut.something(instance) # This should called mock.method and checks the result.   
  6.     self.assertTrue(instance.method.called)  
Both methods do the same thing. I am unsure of the differences. 

Could anyone enlighten me? 

How-To 
mock.patch is a very very different critter than mock.Mockpatch replaces the class with a mock object and lets you work with the mock instance. Take a look at this snippet: 
>>> import mock
>>> class MyClz(object):
... def __init__(self):
... print 'Created MyClz@{0}'.format(id(self))
...
>>> def create_instance():
... return MyClz()
...
>>> x = create_instance() // As expected. The MyClz instance is created.
Created MyClz@140331590049680
>>> @mock.patch('__main__.MyClz') // Here we patch the '__main__.MyClz' from create_instance2
... def create_instance2(MyClz):
... MyClz.return_value = 'foo'
... return create_instance()
...
>>> i = create_instance2()
>>> i
'foo' // The MyClz.return_value = 'foo'
>>> def create_instance(): // Let's rewrite create_instance to make thing clear
... print MyClz
... return MyClz()
...
>>> create_instance2() // Using the patched MyClz

'foo'

>>> create_instance() // The create_instance is not impacted by patched MyClz

Created MyClz@37128016
<__main__ .myclz="" 0x2368750="" at="" object="">

patch replaces MyClz in a way that allows you to control the usage of the class in functions that you call. Once you patch a class, references to the class are completely replaced by the mock instance

mock.patch is usually used when you are testing something that creates a new instance of a class inside of the test. mock.Mock instances are clearer and are preferred. If your self.sut.something method created an instance of MyClz instead of receiving an instance as a parameter, then mock.patch would be appropriate here.

沒有留言:

張貼留言

[Linux 常見問題] What's the best way to send a signal to all members of a process group?

Source From  Here   Question   I want to  kill a whole process tree.  What is the best way to do this using any common scripting languages? ...