2

I have the following my_func.py with create_config function.

*my_func.py

from fabric.state import env

def create_config(node_name):
    config = {
    "log_level": "INFO",
    "addr1": "127.0.0.1",
    }
    config["addr2"] = env.host
    return config

I tried the following approach to mock env.host variable where env is an import from fabric.state.

*test.py

import unittest
import my_func
import mock


class MyTestCase(unittest.TestCase):
    def setUp(self):
        self.master_config = {
              "log_level": "INFO",
              "addr2": "0.0.0.0",
              "addr1": "127.0.0.1",
        }

    @mock.patch('env.host')
    def test_create_consul_config(self, mock_host):
        mock_host.return_value = "0.0.0.0"
        result = my_func.create_config('master')
        self.assertDictEqual(self.master_config, result)


if __name__ == '__main__':
    unittest.main()

I am getting import error with 'env'. What is the best way to mock variable within a function with python mock.

ImportError: No module named env
1
  • the code says provision but you label the file my_func.py which one is it? Commented Jan 16, 2019 at 23:41

2 Answers 2

1

mock variable env.host?

get the type of env first

In [6]: from fabric.state import env

In [7]: type(env)
Out[7]: fabric.utils._AttributeDict

env.host is instance variable of a class, the mock is a little different, mock_env is object(AttributeDict), the assignment of instance_variable host is direct assignment, not with a return_value

@mock.patch('my_func.env')
def test_create_consul_config(self, mock_env):
    mock_env.host = 'xxx'
    result = my_func.create_config('master')

    self.assertDictEqual(self.master_config, result)
Sign up to request clarification or add additional context in comments.

3 Comments

now getting AttributeError: host, I can see the "0.0.0.0" in mock_host object's return_value but it is not being assigned to config["addr2"]
@Anish, actually looking back, @mock.patch('my_func.env') make more sense than mock env.host
@Anish, the host is a instance variable, which ends up with different patching technique
0

From the unittest.mock documentation on patch (note target is the first argument of patch):

target should be a string in the form 'package.module.ClassName'. The target is imported and the specified object replaced with the new object, so the target must be importable from the environment you are calling patch() from. The target is imported when the decorated function is executed, not at decoration time.

So you need to include the full path to the function you are patching. Note also in where to patch that the target should be the path to where the function/object is used, not where it is defined.

So changing your patch call to:

@mock.patch("my_func.env.host")

should fix the ImportError.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.