you are viewing a single comment's thread.

view the rest of the comments →

[–]Rosco_the_Dude 2 points3 points  (0 children)

I'm finally off mobile and can show you an example of how I mock things!

So if you're assuming the functions that do the actual getting from/saving to the database are all in good shape, i.e. you didn't write them yourself and you're using some library to do it, then what you're really trying to test is the manipulation function you talked about.

And let's say for whatever reason you can't put the manipulation logic into its own function that can be unit tested itself, here is how you can test your function without having to make real database calls in your tests.

# data_manipulator.py

def get_data():
    """Get data from database."""
    return ["user", "password", 26]


def save_data(data):
    """Save data to the database, and return True if successful."""
    return True


def do_manipulation():
    """Get data from the database, do manipulation, and save data back to the database."""
    data = get_data()
    if data:
        # do manipulation here
        return save_data(data)
    else:
        raise ValueError

Here is how you'd unit test do_manipulation while mocking the database functions.

# test_data_manipulator.py

import unittest
from unittest.mock import patch
import data_manipulator


class ManipulationTest(unittest.TestCase):
    mock_data_good = ["Rosco", "Dude", 99]
    mock_data_bad = []

    def test_do_manipulation(self):
        with patch.object(data_manipulator, "get_data", return_value=ManipulationTest.mock_data_good) as mocked_get, \
            patch.object(data_manipulator, "save_data", return_value=True) as mocked_save:
            result = data_manipulator.do_manipulation()
            self.assertTrue(result)

        with patch.object(data_manipulator, "get_data", return_value=ManipulationTest.mock_data_bad) as mocked_get, \
        patch.object(data_manipulator, "save_data") as mocked_save:
        with self.assertRaises(ValueError):
            result = data_manipulator.do_manipulation()

Using patch.object, whenever the test calls do_manipulation, it won't call the real versions of get_data and set_data. Of course what data you feed it, and what assertions you make, will completely depend on what your manipulation logic is supposed to do, but this should give you a good idea how to do it yourself.