How to mock a class and its attributes at the same time

Question:

I have a class ClassA which is a list of ClassB.element objects. See below

class ClassA:

    element = []

    def __init__(self, data_object):

        for content in data_object.objects:
            element.append(ClassB(content).element)

class ClassB:

    element = ""

    def __init__(self, content)
        ...

I am currently trying to create a unit test for the __init__ method of ClassA, but I don’t want it to rely on ClassB and for that matter on data_object.objects. What I would like to achieve is for ClassB(content).element to return a predefined list of values, e.g. ["foo", "bar"]. So I would get something like

def test_class_a_init():
    class_a_obj = ClassA(data_object=MagicMock())
    ...
    assert class_a_obj.element == ["foo", "bar"]

How would I go about doing this?

Asked By: OrlandoLuke

||

Answers:

You havent written all of your code to make this work, so I assume your classes look like this:

class ClassA:

    element = []

    def __init__(self, data_object):
        for content in data_object.objects:
            self.element.append(ClassB(content).element)

class ClassB:

    element = ""

    def __init__(self, content):
        self.element=content

In which case, you can do:

class MagicMock:
    objects = ["foo", "bar"]


class_a_obj = ClassA(data_object=MagicMock())
assert class_a_obj.element == ["foo", "bar"]

Do remove the dependency of ClassB, you can use dependency injection in ClassA:

from typing import Type

class ClassB:

    element = ""

    def __init__(self, content):
        self.element=content


class ClassA:

    element = []

    def __init__(self, data_object, child_obj: Type[ClassB] = ClassB):
        for content in data_object.objects:
            self.element.append(child_obj(content).element)
Answered By: Tom McLean
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.