如何在python中模拟链式函数调用?

时间:2010-09-28 14:17:49

标签: python django mocking

我正在使用Michael Foord编写的mock库帮助我测试django应用程序。

我想测试一下我正在设置我的查询,但我认为我不需要实际访问数据库,所以我试图模拟查询。

我可以很好地模拟查询的第一部分,但是当我链接其他内容时,我没有得到我想要的结果。

功能:

    @staticmethod
    def get_policies(policy_holder, current_user):
        if current_user.agency:
            return Policy.objects.filter(policy_holder=policy_holder, version__agency=current_user.agency).distinct()
        else:
            return Policy.objects.filter(policy_holder=policy_holder)

和我的测试:第一个断言通过,第二个断言失败。

    def should_get_policies_for_agent__user(self):
        with mock.patch.object(policy_models.Policy, "objects") as query_mock:
            user_mock = mock.Mock()
            user_mock.agency = "1234"
            policy_models.Policy.get_policies("policy_holder", user_mock)
            self.assertEqual(query_mock.method_calls, [("filter", (), {
                'policy_holder': "policy_holder",
                'version__agency': user_mock.agency,
            })])
            self.assertTrue(query_mock.distinct.called)

我很确定问题是初始query_mock在调用.filter()之后返回一个新的模拟,但是我不知道如何捕获那个新模拟并确保调用.distinct()在它上面。

有没有更好的方法来测试我想要的东西?我正在努力确保调用正确的查询。

1 个答案:

答案 0 :(得分:18)

每个模拟对象都保留在调用它时返回的模拟对象。您可以使用模拟对象的return_value属性来获取它。

对于您的示例,

self.assertTrue(query_mock.distinct.called)

distinct在你的mock上没有调用,它是在你的mock的filter方法的返回值上调用的,所以你可以断言,通过这样做来调用distinct:

self.assertTrue(query_mock.filter.return_value.distinct.called)