How can I insert an object into another namespace in python?

I am writing several unittests for code written by someone else here in the office. Python is not the most powerful language. While I was successful with basic unit tests, the python mockery throws me into a loop.

What I need to do is override the ConfigObj call and insert my own config / fixture layout into any ConfigObj call.

settings.py

from configobj import ConfigObj config = ConfigObj('/etc/myapp/config') 

utils.py

 from settings import config """lots of stuff methods using various config values.""" 

What I would like to do, in my unittests for utils.py, insert yourself either for ANY call in ConfigObj, or in setup.py itself.

Many of the mocking libraries expect me to be a Mock for my classes, but in the case of this application it has no explicit classes.

Is it possible to do this, or are the python namespace restrictions too limited that I cannot interfere with which module I am importing myself?

Side note: 2.7 works, so I can not perform any tricks that I read about, starting with version 2.5.

+4
source share
5 answers

If the tests are in a separate file from settings.py and utils.py , you can create a mock.py file

 import configobj class MockConfigObj(object): #mock whatever you wan configobj.ConfigObj = MockConfigObj 

and then import mock before importing (from) any module that imports settings . This will ensure that settings.config using MockConfigObj . If you want a consistent global bullying, import it before any file that configobj imports.

This works because python will store configobj in sys.modules and check this until it is actually read from the file on subsequent import. in mock.py identifier is just a reference to an entry in sys.modules , so any changes you make will be globally visible.

It seems a bit hacked to me, but it's the best I can think of.

+2
source

Python namespaces are not strict at all within the same scope. Just override the variable name containing your object (or the class itself and providing it) in the same scope that you expect from the original, and that is good enough.

Now, no matter what you replace it, it behaves the same, it depends on you ...

+1
source

Could you just overwrite the original function with another?

There are no constants in Python, you can change everything, you can even make True = False .

0
source

I used to come across a similar situation. This is how I would like to address your problem.

Consider a test case for a function from utils.py .

 import utils, unittest class FooFunctionTests(unittest.TestCase): def setUp(self): utils._old_config = utils.config utils.config = MockClass() def tearDown(self): utils.config = utils._old_config del utils._old_config def test_foo_function_returns_correct_value(self): self.assertEqual("success!", utils.foo()) 
0
source

The next page is good for ridicule and import.

http://www.relaxdiego.com/2014/04/mocking-objects-in-python.html

Let's say you have a file called my_package1.py with the following code:

class A(object): def init (self):

and then import this into my_package2.py with code

from my_package1 import A class A(object): def init (self):

The first line my_package2.py creates a variable in the my_package2 namespace named A. Now you have two variables my_package1.A and my_package2.A that point to the same class in memory. If you want the code in my_package2.py to be used for the mocking class A, you will need to mock my_package2.A not my_package1.A

0
source

All Articles