3

Changed the titel to a more common one. I guess the problem is not that class specific.

I want to mock google.cloud.pubsub_v1.SubscriberClient I want to set a fake return value when calling the pull function of the client.

prod code: 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 } ) 

from the prod code above I want to set the return value for calling the pull method. I am creating a pull-response object in the test code.

test code:

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() 

At least the MagicMock is in place (without using the patch the real subscriber is in place). So basically I would say I mocked the subscriberClient. But I cannot set the return_value for calls to the pull method. But there wont be a pull retur value. All I get is another magicMock created.

I do not get it why it is not working. As most stuff I read we usually have to call 'return_value' on the mock, append the name of either the field or function to be set, append that ones 'return_value' and set a value viea MagicMock. The format should be: mockFirst.return_value.second.return_value.third.return_value = Mock(return_value = the_value_to_return)

Hopefully you can explain me what I am doing wrong. Thanks.

edit: tried also the following ones which where the answers in other posts: 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 

none seems to work. the return value of the pull method stays to be a magicMock.

And this is how it looks like in debugging (hovering over response): enter image description here

2 Answers 2

1

I faced the same issue. But can get idea from the details inside MagicMock.

Try to set return value (based on your screenshot)

mock_subscriber.__enter__().pull.return_value = pull_response 
Sign up to request clarification or add additional context in comments.

1 Comment

unfortunately I cannot test it any more
0

It worked for me when I changed the last line in OP's code to

mock_subscriber.return_value.pull.return_value = pull_response 

by replacing MagicMock(return_value = pull_response) with pull_response.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.