如何模拟一个被模拟类的方法

3

将标题更改为更常见的标题。我想问题不是特定于类。

我想模拟google.cloud.pubsub_v1.SubscriberClient 当调用客户端的pull函数时,我想设置一个虚假的返回值。

生产代码: from google.cloud import pubsub_v1

def open_subscription() -> None:
    with pubsub_v1.SubscriberClient() as subscriber:
        logger.info(f'Listening for messages on {config.SUBSCRIPTION_NAME}', {'operation': {'first': True}})

        while True:
            # get messages
            response = subscriber.pull(
                request = {
                    'subscription': config.SUBSCRIPTION_NAME,
                    'max_messages': config.MAX_MESSAGES
                }
            )

从上面的产品代码中,我想要设置调用pull方法的返回值。我正在测试代码中创建一个pull-response对象。

测试代码:

import unittest
from unittest.mock import MagicMock, patch
from app.pubsub import pubsub_service
from google import pubsub_v1
import json
        
class TestPubSubService(unittest.TestCase):
    
    def create_test_message(self):
        message_string = '{"testKey": "testValue"}'
        message_json = json.dumps(message_string, indent=2)
        message_data = message_json.encode('utf-8')
        
        pubsub_message = pubsub_v1.PubsubMessage()
        pubsub_message.data = message_data

        received_message = pubsub_v1.ReceivedMessage()
        received_message.ack_id = "testId"
        received_message.message = pubsub_message

        return received_message
    
    def create_test_pull_response(self, received_message):
        pull_response = pubsub_v1.PullResponse()
        pull_response.received_messages = [received_message]
        return pull_response
    
    @patch('app.pubsub.pubsub_service.pubsub_v1.SubscriberClient')
    def test_open_subscription(self, mock_subscriber):

        test_message = self.create_test_message()
        pull_response = self.create_test_pull_response(test_message)
        mock_subscriber.return_value.pull.return_value = MagicMock(return_value = pull_response)

        pubsub_service.open_subscription()

至少 MagicMock 已经到位了(没有使用 patch,真实的订阅者已经就位)。 因此,我可以说我模拟了 subscriberClient。 但是,我无法为对 pull 方法的调用设置 return_value。 但是不会有 pull 的返回值。我得到的只是另一个魔术 Mock。

我不明白为什么它不起作用。 正如我读到的大部分内容一样,我们通常需要在 Mock 上调用 'return_value',将要设置的字段或函数的名称附加到其中,附加该字段或函数的 'return_value' 并通过 MagicMock 设置一个值。 格式应该是: mockFirst.return_value.second.return_value.third.return_value = Mock(return_value = 要返回的值)

希望你能解释一下我做错了什么。 谢谢。

编辑:我也尝试了其他帖子中的答案: Mocking Method Calls In Python Mock a method of a mocked object in Python?

mock_subscriber.pull.return_value = pull_response
mock_subscriber.return_value.pull.return_value = pull_response

没有任何方法有效。pull方法的返回值仍然是一个magicMock。
以下是调试时的情况(悬停在响应上): enter image description here
2个回答

1

我曾经遇到过同样的问题。但是可以从MagicMock的详细信息中得到一些想法。

尝试设置返回值(根据您的截图)。

mock_subscriber.__enter__().pull.return_value = pull_response

很遗憾,我无法再进行测试了。 - Kaspatoo

0
当我将OP代码中的最后一行改为这样时,它对我起作用了。
mock_subscriber.return_value.pull.return_value = pull_response

通过将MagicMock(return_value = pull_response)替换为pull_response

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接