dynaconf: [bug] Testing and mocking docs are wrong

Describe the bug The docs in https://dynaconf.readthedocs.io/en/latest/guides/testing.html explain how to test with dynaconf. The point is that if you follow the explanation, you will see AttributeError: 'DynaconfDict' object has no attribute 'current_env'

To Reproduce

Just try to follow the steps in https://dynaconf.readthedocs.io/en/latest/guides/testing.html

Expected behavior The code don’t fail and the mock can be used.

Debug output

Debug Output
Traceback (most recent call last):
  File "lalala.py", line 5, in <module>
    toml_loader.load(mocked_settings, filename="test_conf.toml", env="testing")
  File "/home/angel/.virtualenvs/navi-Pag0EvBg/lib/python3.6/site-packages/dynaconf/loaders/toml_loader.py", line 38, in load
    loader.load(filename=filename, key=key, silent=silent)
  File "/home/angel/.virtualenvs/navi-Pag0EvBg/lib/python3.6/site-packages/dynaconf/loaders/base.py", line 69, in load
    env_list = build_env_list(self.obj, self.env)
  File "/home/angel/.virtualenvs/navi-Pag0EvBg/lib/python3.6/site-packages/dynaconf/utils/__init__.py", line 220, in build_env_list
    if obj.current_env and obj.current_env not in env_list:
AttributeError: 'DynaconfDict' object has no attribute 'current_env'

Environment (please complete the following information):

  • OS: Ubuntu 18.04
  • Dynaconf Version 2.2

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 5
  • Comments: 15 (5 by maintainers)

Most upvoted comments

I think the easiest way is to dump a settings file to a temporary location and load it. Something like:

@pytest.fixture
def mock_settings_path(tmpdir):
    settings_path = tmpdir.mkdir("test_package").join("settings.py")
    settings_path.write(
        textwrap.dedent(
            f"""
                SETTING_ONE = True
            """
        )
    )
    return str(settings_path) 

And you can use the fixture as follows:

def test_settings_file(mock_settings_path):
    settings = LazySettings(settings_file=mock_settings_path)
    assert SETTING_ONE == True

The beauty of this approach is that you can actually add a Mock to your mock settings file, e.g.

# in your test module
MOCK_SETTING_TWO = MagicMock()

# in your mock settings file
f"""
from {__name__} import MOCK_SETTING_TWO
SETTING_TWO = MOCK_SETTING_TWO
"""

Nice insight! @rochacbruno So actually there’s no way to mock settings? I was digging in the tests but didn’t find anything to load a json or a dict and being able to mock tests.

I wrote something like this. Not optimum but for now it works ok for my purposes. Maybe somebody finds it useful.


    from dynaconf import LazySettings
    from dynaconf.loaders.json_loader import load

    mocked_settings = LazySettings(environments=True, ENV_FOR_DYNACONF="DEFAULT")

    data = """
    {
        "default" : {
            "SETTING_ONE": false,
            "SETTING_TWO": "test"
        }
    }
    """
    load(mocked_settings, filename=data)

Thanks!

Another option would be to use Monkeypatch

def __init__(self, *args, **kwargs):
        self._loaded_files = []
+       self.current_env = kwargs.get('env', 'development')
        super(DynaconfDict, self).__init__(*args, **kwargs)

@mazzi In fact, MonkeyPatching Dynaconf settings in Pytest doesn’t work, unfortunately. Setting values don’t change that way.

We have the same issue here with additional accessors as as_dict or as_int here:

AttributeError: 'DynaconfDict' object has no attribute 'as_int'