# Mocking rpc call for unit testing with pytest

**URL:** <https://discourse.nameko.io/t/mocking-rpc-call-for-unit-testing-with-pytest/604>\
**Category:** Uncategorized\
**Created:** [July 2, 2020, 5:48pm UTC](https://discourse.nameko.io/t/mocking-rpc-call-for-unit-testing-with-pytest/604 "2020-07-02T17:48:51Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![devnrj07](https://avatars.discourse-cdn.com/v4/letter/d/b2d939/32.png) [@devnrj07](https://discourse.nameko.io/u/devnrj07)\
**Post date:** [July 2, 2020, 5:48pm UTC](https://discourse.nameko.io/t/mocking-rpc-call-for-unit-testing-with-pytest/604/1 "2020-07-02T17:48:51Z")

</div>

Hi fellow developers, I’m facing an issue with unit testing a service which calls other service via rpc. What I’m trying to do is basically, mock the rpc response from other service, as they have done in the nameko example for testing gateway.  
I’m not sure if that’ s right approach, if anyone could point in my right direction, that would really be great. I’m following nameko-example from offical [nameko](https://github.com/nameko/nameko-examples/tree/master/gateway/test) repository, I use same conftest file, to provide mocked rpc and then retuen a custom response.

---

<div class="post-metadata">

**Author:** ![devnrj07](https://avatars.discourse-cdn.com/v4/letter/d/b2d939/32.png) [@devnrj07](https://discourse.nameko.io/u/devnrj07)\
**Post date:** [July 3, 2020, 8:31pm UTC](https://discourse.nameko.io/t/mocking-rpc-call-for-unit-testing-with-pytest/604/2 "2020-07-03T20:31:14Z")

</div>

More details about the problem, since I’m unable to edit the post I’m writing it here.

Hi fellow developers, I’m facing an issue with unit testing a service which calls other service via rpc. What I’m trying to do is basically, mock the rpc response from other service, as they have done in the nameko example for testing gateway.  
I’m not sure if that’ s right approach, if anyone could point in my right direction, that would really be great. I’m following nameko-example from offical [nameko](https://github.com/nameko/nameko-examples/tree/master/gateway/test) repository, I use same conftest file, to provide mocked rpc and then return a custom response.

I think I didn’t provide sufficient info, the thing is I can’t paste the code here. But the gist of it is

Service ABC

```
    class ABCService: 
         xyx_rpc = RpcProxy('XYZ')
        @rpc
        def handle_task(self, *task):
         ....
         rpc_response = xyz_rpc.perform_task(token, details)
        ....
        return MySchema().dump(data_map)

```

Service XYZ

```
 class XYZService: 
             
            @rpc
            def perform_task(self, token, details):
             ....
            some business logic
            ....
            return ResponseSchema().dump(data_map)

```

Test class ABC

```
class TestABCservice:

        def test_handle_task(self, abc_service):
         abcService = ABCService()    
     #I want to mock response from xyzservice.perform_task method
         abc_service.xyz_rpc.perform_task.return_value = { **'some':'dummy response'** }
         response = abcService.handle_task(*dummy_task)
        
       assert response = { 'status : 'success', **'some':'dummy response'** , ....}

```

here, abc\_service is a fixture with replaced dependencies using conftest.py from gateway service in nameko example.

The issue is I get this error, I’m guessing it didn’t get mocked.

> AttributeError: ‘ServiceRpc’ object has no attribute ‘perform\_task’

Any help would really appreciated

---

<div class="post-metadata">

**Author:** ![devnrj07](https://avatars.discourse-cdn.com/v4/letter/d/b2d939/32.png) [@devnrj07](https://discourse.nameko.io/u/devnrj07)\
**Post date:** [July 3, 2020, 8:33pm UTC](https://discourse.nameko.io/t/mocking-rpc-call-for-unit-testing-with-pytest/604/3 "2020-07-03T20:33:01Z")

</div>

@mattbennett any help will really appreciated. Thanks

---

<div class="post-metadata">

**Author:** ![zsiciarz](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.nameko.io/zsiciarz/32/58_2.png) [@zsiciarz](https://discourse.nameko.io/u/zsiciarz)\
**Post date:** [July 4, 2020, 11:08am UTC](https://discourse.nameko.io/t/mocking-rpc-call-for-unit-testing-with-pytest/604/4 "2020-07-04T11:08:16Z")

</div>

Could you show the definition of abc\_service fixture? Do you use `worker_factory` there?

What works for me is usually something along the lines of:

```
@pytest.fixture
def abc_service():
    return worker_factory(AbcService)

```

And then in the test case:

```
def test_xyz_method(abc_service):
    # abc_service is already an instance of service class, there's no need to instantiate it explicitly
    abc_service.xyz_rpc.perform_task.return_value = "whatever"
    abc_service.handle_task() # this calls the mocked proxy method
```

---

<div class="post-metadata">

**Author:** ![mattbennett](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.nameko.io/mattbennett/32/13_2.png) [@mattbennett](https://discourse.nameko.io/u/mattbennett)\
**Post date:** [July 5, 2020, 9:22pm UTC](https://discourse.nameko.io/t/mocking-rpc-call-for-unit-testing-with-pytest/604/5 "2020-07-05T21:22:31Z")

</div>

The error you’ve posted looks like no mock has been applied. I can’t say for sure what the problem is without seeing your fixture definition, but if you just want to mock the return value of the RPC call, the `worker_factory` pattern @zsiciarz suggests is best.

The `replace_dependencies` fixture is for cases where you want to inject an alternative `DependencyProvider` object, whereas `worker_factory` skips dependency injection completely and replaces the dependency attributes on the service class directly.

---

<div class="post-metadata">

**Author:** ![devnrj07](https://avatars.discourse-cdn.com/v4/letter/d/b2d939/32.png) [@devnrj07](https://discourse.nameko.io/u/devnrj07)\
**Post date:** [July 6, 2020, 8:29am UTC](https://discourse.nameko.io/t/mocking-rpc-call-for-unit-testing-with-pytest/604/7 "2020-07-06T08:29:31Z")

</div>

Thank you @zsiciarz and @mattbennett for the reply and sorry, for delayed reply, weekend and then different timezones.  
Anyway, I tried what @zsiciarz suggested using worker\_factory and yes, @mattbennett, I was using replace\_dependencies in my fixture which I copied and edited from nameko example.

Thank you so much, it worked. I had feeling that I’m doing something wrong because this seems like a pretty common case.

Also, any suggestions on how to test db layer or database dependency class in case of mongodb. I’ve heard [mongomock] is a good library.

---

<div class="post-metadata">

**Author:** ![mattbennett](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.nameko.io/mattbennett/32/13_2.png) [@mattbennett](https://discourse.nameko.io/u/mattbennett)\
**Post date:** [July 6, 2020, 1:35pm UTC](https://discourse.nameko.io/t/mocking-rpc-call-for-unit-testing-with-pytest/604/8 "2020-07-06T13:35:52Z")

</div>

When writing and testing DependencyProviders I try to keep the interface with the service class as narrow as possible. Often that means injecting a wrapper class rather than the bare dependency itself.

A silly example:

You’re writing a service that manages a zoo. State about the animals is stored in Mongo. Rather than having a DependencyProvider that returned a bare mongo client, I’d return something with meaningful methods for the service:

**DO THIS**

```python
class ZooService:
    name = "zoo"

    self.animals = Animals() # DependencyProvider

    @entrypoint
    def method(self):
        all_mammals = self.animals.list_mammals()

```

**NOT THIS**

```auto
class ZooService:
    name = "zoo"

    self.mongo = MongoClient() # DependencyProvider

    @entrypoint
    def method(self):
        all_mammals = self.mongo.animals.filter(type=="mammal") # or whatever

```

If you follow this pattern it’s trivial to test your service method with mock responses using the `worker_factory`.

It’s much simpler to test a specific DependencyProvider in isolation too. If your equivalent of the `Animals` DP used Mongo it’d probably be quite easy to use mongomock in place of the real mongo client.

---

<div class="post-metadata">

**Author:** ![devnrj07](https://avatars.discourse-cdn.com/v4/letter/d/b2d939/32.png) [@devnrj07](https://discourse.nameko.io/u/devnrj07)\
**Post date:** [July 6, 2020, 1:48pm UTC](https://discourse.nameko.io/t/mocking-rpc-call-for-unit-testing-with-pytest/604/9 "2020-07-06T13:48:02Z")

</div>

Thank you again, for jolting an example again.  
I see your point, and I’ve noticed same pattern in nameko example. I’m afraid I’m doing what you described not to do. I use this [nameko-mongo](https://pypi.org/project/nameko-mongodb/) dependency and import it directly into my service class, which is anti-pattern. I’ll refactor this as per suggested example. Thanks again.

and one last question, I can’t seem to find any docs or examples on mongomock, it’s just this [repo] and this [stackoverflow](https://stackoverflow.com/a/51994349) answer. Am I overlooking something ?

---

<div class="post-metadata">

**Author:** ![mattbennett](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.nameko.io/mattbennett/32/13_2.png) [@mattbennett](https://discourse.nameko.io/u/mattbennett)\
**Post date:** [July 6, 2020, 2:02pm UTC](https://discourse.nameko.io/t/mocking-rpc-call-for-unit-testing-with-pytest/604/10 "2020-07-06T14:02:21Z")

</div>

I’ve not used mongomock before I’m afraid
