使用模拟补丁模拟实例方法


82

我正在尝试使用富有想象力的Mock测试库测试Django应用程序时模拟某些东西。我似乎无法完全正常工作,我正在尝试这样做:

models.py

from somelib import FooClass

class Promotion(models.Model):
    foo = models.ForeignKey(FooClass)
    def bar(self):
       print "Do something I don't want!"


test.py

class ViewsDoSomething(TestCase):
    view = 'my_app.views.do_something'

    def test_enter_promotion(self):
        @patch.object(my_app.models.FooClass, 'bar')
        def fake_bar(self, mock_my_method):
            print "Do something I want!"
            return True

        self.client.get(reverse(view))

我究竟做错了什么?


bar实际上是“实例方法”,其唯一参数是self。要成为类方法,需要使用进行参数化cls,并且可以将其调用为Promotion.foo()
cavaunpeu 2015年

可修补对象需要像这样被引用: @patch.object('my_app.models.FooClass', 'bar')
Lasma

2
@cavaunpeu -不(仅仅)与参数化cls,但更重要的是(因为selfcls做蟒蛇并不意味着什么特殊的),装饰着@classmethod
dwanderson

Answers:


67

为了增加Kit的答案,指定第三个参数patch.object()可以指定模拟对象/方法。否则,将使用默认MagicMock对象。

    def fake_bar(self):
        print "Do something I want!"
        return True

    @patch.object(my_app.models.FooClass, 'bar', fake_bar)
    def test_enter_promotion(self):
        self.client.get(reverse(view))
        # Do something I want!

请注意,如果指定了模拟对象,则默认值MagicMock()不再传递到修补的对象中,例如,不再:

def test_enter_promotion(self, mock_method):

但反而:

def test_enter_promotion(self):

http://www.voidspace.org.uk/python/mock/patch.html#patch-object


我更喜欢这种实现。这一点更加清楚,尤其是对于单元测试的初学者而言。
Dorcioman

35

啊,我对在哪里应用补丁装饰感到困惑。固定:

class ViewsDoSomething(TestCase):
    view = 'my_app.views.do_something'

    @patch.object(my_app.models.FooClass, 'bar')
    def test_enter_promotion(self, mock_method):
        self.client.get(reverse(view))

20
您现在在哪里模拟方法与伪实现之间的联系?
物理

@physicalattraction,mock_method通过传递给测试函数的参数进行连接。我已经可以在一项测试中使用此技术。当您只想验证是否调用了模拟方法时,这很有用。
Kalyan Vedala

@ rcode74:如何在测试方法内部修补(某个其他对象)实例的方法。例如:def my_method_to_be_tested(...):r = some_script.some_class(...); r.how_to_patch_this_method。
imsrgadich

1
@imsrgadich,您将执行类似r.how_to_patch_this_method = MagicMock()的操作。您可以查看MagicMock文档,以了解如何将行为分配给模拟对象。
Kalyan Vedala '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.