Python unittest mock an attribute

66 Views Asked by At

I have a device attached to the PC and I wrote a Python wrapper for its API so I can control it. I wrote unittest for my code.

Some values are obtained from the device itself and it cannot be changed.

For example, to check if the device is connected I have to read it from an attribute and I cannot change it.

A really simplified version:

Please notice I know there might be some undefined classes or variables, but it is due to code simplification.

from win32com import client
from pythoncom import com_error


class Device:
    def __init__(self, port):
        try:
            self.device = client.Dispatch(port)
        except com_error:
            raise WrongSelect(
                f"No such {self.__class__.__name__} as {port}")

    def get_description(self):
        if self.device.connected:
            return self.device.Description
        
        raise NotConnected("Device is not Connected")

Here the test code:

import unittest
from unittest.mock import patch


class TestDevice(unittest.TestCase):
    def setUp(self):
        self.PORT = "A PORT"
        self.DEVICE = Device(self.PORT)

    def test_get_description(self):
        description = self.DEVICE.get_description()
        self.assertIsInstance(description, str)

    def test_get_description_not_connected(self):
        # How to mock self.DEVICE.device.connected
        pass

How to mock connected value of the object?

1

There are 1 best solutions below

1
On

You can use unittest.mock.patch.object as a context manager to temporarily change the value of an attribute of an object in a local variable within the context:

# test that get_description raises NotConnected when device.connected is False
def test_get_description_not_connected(self):
    with patch.object(self.DEVICE.device, 'connected', False):
        with self.assertRaises(NotConnected):
            self.DEVICE.get_description()