Ryan Hardin
Ryan Hardin

Reputation: 81

Mock an external service instantiated in python constructor

I'm working on unit tests for a service I made that uses confluent-kafka. The goal is to test successful function calls, exception errors, etc. The problem I'm running into is since I'm instantiating the client in the constructor of my service the tests are failing since I'm unsure how to patch a constructor. My question is how do I mock my service in order to properly test its functionality.

Example_Service.py:

from confluent_kafka.schema_registry import SchemaRegistryClient

class ExampleService:
  def __init__(self, config):
    self.service = SchemaRegistryClient(config)

  def get_schema(self):
    return self.service.get_schema()   

Example_Service_tests.py

from unittest import mock

@mock.patch.object(SchemaRegistryClient, "get_schema")
def test_get_schema_success(mock_client):
    schema_Id = ExampleService.get_schema()
    mock_service.assert_called()

Upvotes: 0

Views: 425

Answers (2)

Sandeep Fatangare
Sandeep Fatangare

Reputation: 2144

Two ways

mock entire class using @mock.patch(SchemaRegistryClient) OR replace @mock.patch.object(SchemaRegistryClient, "get_schema") with

@mock.patch.object(SchemaRegistryClient, "__init__")
@mock.patch.object(SchemaRegistryClient, "get_schema")

Upvotes: 0

chepner
chepner

Reputation: 531345

The problem is that you aren't creating an instance of ExampleService; __init__ never gets called.

You can avoid patching anything by allowing your class to accept a client maker as an argument (which can default to SchemaRegistryClient:

class ExampleService:
    def __init__(self, config, *, client_factory=SchemaRegistryClient):
        self.service = client_factory(config)

    ...

Then in your test, you can simply pass an appropriate stub as an argument:

def test_get_schema_success():
    mock_client = Mock()
    schema_Id = ExampleService(some_config, client_factory=mock_client)
    mock_client.assert_called()

Upvotes: 1

Related Questions