How do i mock an external libraries' classes/functions such as yaml.load() or Box() in python

Question:

How would i go about testing the following class and its functions?

import yaml
from box import Box
from yaml import SafeLoader


class Config:
    def set_config_path(self):
        self.path = r"./config/datasets.yaml"
        return self.path

    def create_config(self):
        with open(r"./config/datasets.yaml") as f:
            self.config = Box(yaml.load(f, Loader=SafeLoader))
        return self.config

These are the current tests I have created so far, but i am struggling with the final function:

import unittest
from unittest.mock import mock_open, patch
from src.utils.config import Config


class TestConfig(unittest.TestCase):
    def setUp(self):
        self.path = r"./config/datasets.yaml"

    def test_set_config_path(self):
        assert Config.set_config_path(self) == self.path

    @patch("builtins.open", new_callable=mock_open, read_data="data")
    def test_create_config(self, mock_file):
        assert open(self.path).read() == "data"

How would i go about testing/mocking the Box() and yaml.load() methods.

I have tried mocking where the Box and yaml.load() functions are used in the code – however i dont fully understand how this works.

Ideally I’d want to be able to pass a fake file to the with open() as f:, which then is read by Box and yaml.load to output a fake dictionary config.

Thanks!

Asked By: Ainceer

||

Answers:

The thing to remember about unit tests is that the goal is to test public interfaces of YOUR code. So to mock a third parties code is not really a good thing to do though in python it can be done but would be alot of monkey patching and other stuff.

Also creating and deleting files in a unit test is fine to do as well. So you could just create a test version of the yaml file and store it in the unit tests directory. During a test load the file and then do assertions to check that it was loaded properly and returned.

You wouldn’t do a unit test checking if Box was initialized properly cause that should be in another test or test case. Unless its a third party then you would have to make sure it was initialized properly cause it’s not your code.

So create a test file, open it and load it as yaml then pass it into Box constructor. Do assertions to make sure those steps completed properly. No need to mock yaml or Box.

Answered By: TeddyBearSuicide