简体   繁体   中英

how to mock dependency in python

I am new to python unit testing framework and lot of confusion in mocking dependency.

I am trying to write unit tests for below member function of a class, ( check_something() ):

class Validations:    
    def check_something(self):
        abc = os.environ['PLATFORM']
        xyz = Node()
        no_of_nodes = len(xyz.some_type_var)
        if abc != "X_PLATFORM" or no_of_nodes != 1:
            raise someException()

How do we eliminate dependency ?

  1. Need to mock Node() ?
  2. How do we make sure abc is assigned with X_PLATFORM ?
  3. How to assign value 1 to variable no_of_nodes ? which is in turn derived from Node() object.

     class Node(object): def __init__(self): self.nodes = DEF() self.some_type_var = someclass().getType() self.localnode = os.environ['HOSTNAME'] self.peertype = self.get_peer_type() def get_peer_type(self): return node 

I tried writing below unit test. I am unable to check for fail and pass condition. I am not sure whether it is correct or not.

class TestValidation(unittest.TestCase):

    @mock.patch.object(Node, "get_peer_type")
    @mock.patch('somefile.Node', spec=True)
    def test_1(self, mock_object1, mock_object2):
        os.environ['PLATFORM'] = 'X_PLATFORM'
        obj = Validations()
        self.assertRaises(someException, obj.check_something)

Validation class uses Node() Class object and Node class uses some other class.

  1. How to make sure exception is raised or not depending on the condition?

Yes, you'd mock anything external to the unit of code under test. Here that means the os.environ dictionary and the Node() class.

The patch needs to be applied to the module your code is in; @mock.patch('somefile.Node', spec=True) is correct if somefile is the same module as Validations ; see the Where to patch section as to why that is.

I'm not sure that using spec=True is all that helpful here; your Node attributes are all instance attributes created in Node.__init__ , so they are not available on the class , which is what informs the spec. See the section on autospeccing on how to overcome that if you really want to set a spec.

abc is set from os.environ , you can use the patch.dict() object to patch that dictionary for your needs.

The xyz = len(xyz.some_type_var) is simply handled by either setting the some_type_var attribute to an object with the right length, or by setting xyz.some_type_var.__len__.return_value , since it is the xyz.some_type_var.__len__() method that is called for the len() function.

So, to test, you'd do:

class TestValidation(unittest.TestCase):
    @mock.patch('somefile.Node')
    def test_1(self, mock_node):
        # set up the Node() instance, with the correct length
        node_instance = mock_node.return_value
        node_instance.some_type_var.__len__ = 2
        # or, alternatively, node_instance.some_type_var = (1, 2)

        # set up os.environ['PLATFORM']
        with mock.patch.dict('os.environ', PLATFORM='X_PLATFORM'):
            obj = Validations()
            with self.assertRaises(someException):
                obj.check_something()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM