Python返回MagicMock对象而不是return_value


86

我有一个Python文件a.py包含两个类AB

class A(object):
    def method_a(self):
        return "Class A method a"

class B(object):
    def method_b(self):
        a = A()
        print a.method_a()

我想通过嘲笑method_b在课堂上B进行单元测试A。这是testa.py用于此目的的文件内容:

import unittest
import mock
import a


class TestB(unittest.TestCase):

    @mock.patch('a.A')
    def test_method_b(self, mock_a):
        mock_a.method_a.return_value = 'Mocked A'
        b = a.B()
        b.method_b()


if __name__ == '__main__':
    unittest.main()

我希望得到Mocked A输出。但是我得到的是:

<MagicMock name='A().method_a()' id='4326621392'>

我在哪里做错了?


1
测试时,A()返回return_valuefrom mock_A(不是常规的MagicMock,因为您没有指定其他任何东西),它不是class的实例A。您需要将其设置return_value为已定义的内容method_a
jonrsharpe '16

3
mock_a.method_a.return_value ='模拟的A'=>模拟_a()。method_a.return_value ='模拟的A'应该更好:)
Ali SAID OMAR

@AliSAIDOMAR完全正确,应该是调用的返回值mock_a,而不是方法mock_a本身。
jonrsharpe'7

1
@jonrsharpe。感谢您的解释。我刚试过 无论mock_a().method_a.return_value = 'Mocked A'mock_a.return_value.method_a.return_value = 'Mocked A'工作。非常感谢您的评论。您能继续回答吗?
Mehdi Jafarnia Jahromi'7

@MehdiJafarniaJahromi非常感谢!
尼亚克罗斯

Answers:


96

当您使用时@mock.patch('a.A'),您正在用替换A被测代码中的类mock_a

B.method_b你接盘a = A(),这是现在a = mock_a()-即areturn_valuemock_a。由于您尚未指定此值,因此它是常规值MagicMock;这个也没有配置,因此MagicMock在调用方法时会得到默认响应(还有另一个响应)。

相反,你要配置return_valuemock_a有适当的方法,你可以做两种:

mock_a().method_a.return_value = 'Mocked A' 
    # ^ note parentheses

或者,也许更明确地:

mock_a.return_value.method_a.return_value = 'Mocked A'

您的代码在这种情况下可以工作a = A(分配类,而不创建实例),那样便a.method_a()可以触发您的模拟方法。


4
太棒了 你让我今天一整天都感觉很好。
维沙尔'18

@jonrsharpe,您好:我正在使用带有df.columns的熊猫数据来检查我的if条件。它不使用括号(即,不可调用)。在这种情况下,我该怎么做才能返回列表。谢谢!
imsrgadich

@imsrgadich您需要模拟吗?只需构建适当的数据框,并将其视为测试值即可。
jonrsharpe

@jonrsharpe是的,我可以这样做,但是我还要在我需要断言的被调用方法中执行df.drop,而且我还没有从被调用方法返回数据帧。这就产生了一个问题。我找到了一种mock_data.configure_mock(columns='my_column')解决问题的方法。感谢您的回复。(ref:bradmontgomery.net/blog/how-world-do-you-mock-name-attribute
imsrgadich

当您在同一测试中模拟两个SQLAlchemy模型时,这似乎不起作用。第一个可以正常运行,但是第二个无论您定义什么都将返回MagicMock。
Juha Untinen
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.