模拟一个类:Mock()或patch()?

时间:2022-04-27 22:43:51

I am using mock with Python and was wondering which of those two approaches is better (read: more pythonic).

我正在使用Python的模拟,并想知道这两种方法中的哪一种更好(阅读:更pythonic)。

Method one: Just create a mock object and use that. The code looks like:

方法一:只需创建一个模拟对象并使用它。代码如下:

def test_one (self):
    mock = Mock()
    mock.method.return_value = True 
    self.sut.something(mock) # This should called mock.method and checks the result. 
    self.assertTrue(mock.method.called)

Method two: Use patch to create a mock. The code looks like:

方法二:使用补丁创建模拟。代码如下:

@patch("MyClass")
def test_two (self, mock):
    instance = mock.return_value
    instance.method.return_value = True
    self.sut.something(instance) # This should called mock.method and checks the result. 
    self.assertTrue(instance.method.called)

Both methods do the same thing. I am unsure of the differences.

两种方法都做同样的事情。我不确定这些差异。

Could anyone enlighten me?

谁能开导我?

2 个解决方案

#1


115  

mock.patch is a very very different critter than mock.Mock. patch replaces the class with a mock object and lets you work with the mock instance. Take a look at this snippet:

mock.patch是一个非常不同的小动物而不是mock.Mock。 patch使用模拟对象替换该类,并允许您使用模拟实例。看一下这个片段:

>>> class MyClass(object):
...   def __init__(self):
...     print 'Created MyClass@{0}'.format(id(self))
... 
>>> def create_instance():
...   return MyClass()
... 
>>> x = create_instance()
Created MyClass@4299548304
>>> 
>>> @mock.patch('__main__.MyClass')
... def create_instance2(MyClass):
...   MyClass.return_value = 'foo'
...   return create_instance()
... 
>>> i = create_instance2()
>>> i
'foo'
>>> def create_instance():
...   print MyClass
...   return MyClass()
...
>>> create_instance2()
<mock.Mock object at 0x100505d90>
'foo'
>>> create_instance()
<class '__main__.MyClass'>
Created MyClass@4300234128
<__main__.MyClass object at 0x100505d90>

patch replaces MyClass 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.

patch以一种允许您控制所调用函数中类的用法的方式替换MyClass。修补类后,对类的引用将完全被mock实例替换。

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 MyClass instead of receiving an instance as a parameter, then mock.patch would be appropriate here.

mock.patch通常用于测试在测试中创建类的新实例的东西。 mock.Mock实例更清晰,更受欢迎。如果你的self.sut.something方法创建了一个MyClass实例而不是接收一个实例作为参数,那么mock.patch在这里是合适的。

#2


8  

I've got a YouTube video on this.

我有关于此的YouTube视频。

Short answer: Use mock when you're passing in the thing that you want mocked, and patch if you're not. Of the two, mock is strongly preferred because it means you're writing code with proper dependency injection.

简短的回答:当你传递你想要嘲笑的东西时使用模拟,如果你不是,则使用补丁。在这两者中,mock是强烈首选的,因为它意味着您正在编写具有适当依赖注入的代码。

Silly example:

愚蠢的例子:

# Use a mock to test this.
my_custom_tweeter(twitter_api, sentence):
    sentence.replace('cks','x')   # We're cool and hip.
    twitter_api.send(sentence)

# Use a patch to mock out twitter_api. You have to patch the Twitter() module/class 
# and have it return a mock. Much uglier, but sometimes necessary.
my_badly_written_tweeter(sentence):
    twitter_api = Twitter(user="XXX", password="YYY")
    sentence.replace('cks','x') 
    twitter_api.send(sentence)

#1


115  

mock.patch is a very very different critter than mock.Mock. patch replaces the class with a mock object and lets you work with the mock instance. Take a look at this snippet:

mock.patch是一个非常不同的小动物而不是mock.Mock。 patch使用模拟对象替换该类,并允许您使用模拟实例。看一下这个片段:

>>> class MyClass(object):
...   def __init__(self):
...     print 'Created MyClass@{0}'.format(id(self))
... 
>>> def create_instance():
...   return MyClass()
... 
>>> x = create_instance()
Created MyClass@4299548304
>>> 
>>> @mock.patch('__main__.MyClass')
... def create_instance2(MyClass):
...   MyClass.return_value = 'foo'
...   return create_instance()
... 
>>> i = create_instance2()
>>> i
'foo'
>>> def create_instance():
...   print MyClass
...   return MyClass()
...
>>> create_instance2()
<mock.Mock object at 0x100505d90>
'foo'
>>> create_instance()
<class '__main__.MyClass'>
Created MyClass@4300234128
<__main__.MyClass object at 0x100505d90>

patch replaces MyClass 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.

patch以一种允许您控制所调用函数中类的用法的方式替换MyClass。修补类后,对类的引用将完全被mock实例替换。

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 MyClass instead of receiving an instance as a parameter, then mock.patch would be appropriate here.

mock.patch通常用于测试在测试中创建类的新实例的东西。 mock.Mock实例更清晰,更受欢迎。如果你的self.sut.something方法创建了一个MyClass实例而不是接收一个实例作为参数,那么mock.patch在这里是合适的。

#2


8  

I've got a YouTube video on this.

我有关于此的YouTube视频。

Short answer: Use mock when you're passing in the thing that you want mocked, and patch if you're not. Of the two, mock is strongly preferred because it means you're writing code with proper dependency injection.

简短的回答:当你传递你想要嘲笑的东西时使用模拟,如果你不是,则使用补丁。在这两者中,mock是强烈首选的,因为它意味着您正在编写具有适当依赖注入的代码。

Silly example:

愚蠢的例子:

# Use a mock to test this.
my_custom_tweeter(twitter_api, sentence):
    sentence.replace('cks','x')   # We're cool and hip.
    twitter_api.send(sentence)

# Use a patch to mock out twitter_api. You have to patch the Twitter() module/class 
# and have it return a mock. Much uglier, but sometimes necessary.
my_badly_written_tweeter(sentence):
    twitter_api = Twitter(user="XXX", password="YYY")
    sentence.replace('cks','x') 
    twitter_api.send(sentence)

相关文章