Hi,
I am using v3.0.0rc11. My service is defined as below:
import logging
from nameko import config
from nameko.rpc import rpc
class MyService:
name = config.get('SERVICE_NAME')
logger = logging.getLogger(__name__)
@rpc
def sum(self, num1, num2):
self.logger.info(f'Num1: {num1}, Num2: {num2}')
return num1 + num2
I have written my unit test thus:
from nameko.testing.services import worker_factory
from MySvc.myservice import MyService
class TestMyService:
def setup_method(self):
self.cfg = {
'SERVICE_NAME' : 'MyService'
}
def test_sum(self, container_factory):
cfg = {
'SERVICE_NAME' : 'MyService'
}
svc = worker_factory(MyService, config=cfg)
assert( svc.name == 'MyService' )
assert( svc.sum(2,3) == 5 )
The unit test fails, with this error:
nameko.exceptions.ExtensionNotFound: DependencyProvider(s) 'dict_keys(['config'])' not found on <class 'MySvc.myservice.MyService'>.
What am I doing wrong? How can I pass in config to worker_factory so the config gets passed in to service properly?
Thanks for all the help!
Radha.
Nameko is complaining because worker_factory
expects its arguments to be dependencies to be injected. Service classes don’t need define a config
dependency provider in Nameko 3, because the config
object is a global.
You can update the global config object directly from your test. In fact, the config
object has a patch
method for this purpose. I’ve written some docs on this here Testing services -.
Your service is reading from the config
object at import time, so you need to make sure your test populates the desired configuration beforehand. Moving the import inline is sufficient, or you can use importlib.reload
.
This works:
from nameko.testing.services import worker_factory
from nameko import config
import service # module where MyService is defined
import pytest
import importlib
class TestMyService:
@pytest.fixture
def set_config(self):
with config.patch({"SERVICE_NAME": "MyService"}):
yield
def test_sum(self, set_config):
importlib.reload(service)
svc = worker_factory(service.MyService)
assert( svc.name == 'MyService' )
assert( svc.sum(2,3) == 5 )
Thanks Matt! That works!
Another question related to MyService above: What is the best practice to set the name of a service from a config object?
When service gets imported at import service # module where MyService is defined line, config object is None (config object is not patched yet here), and the line name = config.get(‘SERVICE_NAME’) runs into an error.
Deriving the service name from config is fine. It’s one of the advantages of config
being a global.
It shouldn’t matter if config.get(‘SERVICE_NAME’)
is None
temporarily, as long as you reimport the module after the patch is in place.
What is the error you’re seeing?