0

How can I mock a class to test its methods in isolation when they use instance variables? This is an example of the code I am trying to test.

class Employee:
    def __init__(self, id):
        self.id = id
        self.email = self.set_email()

    def set_email():
        df = get_all_info()
        return df[df[id] == self.id].email[0]

def get_all_info():
    # ...

My thought is to Mock the Employee class then call the set_email method to test it. The testing code:

def test_set_email(get_all_info_mock):
    # ...
    mock_object = unittest.mock.Mock(Employee)

    actual_email = Employee.set_email(mock_object)

    assert actual_email == expected_email

When running the test I get the following error.

AttributeError: Mock object has no attribute 'id'

I tried to follow the directions here: Better way to mock class attribute in python unit test. I've also tried to set the mock as a property mock, id witha side_effect, and id with a return_value but I can't seem to figure it out. I don't want to patch the Employee class because the goal is to test it's methods.

8
  • Try mock_object = unittest.mock.Mock(Employee, autospec=True) Commented Apr 23, 2019 at 16:53
  • I get the same error. Without the autospec=True when debugging the mock object would look like this <Mock spec='Employee' id='259360400'> Commented Apr 23, 2019 at 17:07
  • Don't mock the class; that's what you are testing. Mock get_all_info instead and create a real instance of Employee. Commented Apr 23, 2019 at 17:29
  • @chepner I'm testing set_email. If I create an instance of the employee class it will call all of the methods in __init__ which is what I am trying to avoid. Commented Apr 23, 2019 at 17:32
  • Why? If you mock get_all_info to return a static data frame (instead of querying some outside resource, there's no problem with calling set_email. Commented Apr 23, 2019 at 17:34

1 Answer 1

1

All you need to do is set the id attribute.

def test_set_email(get_all_info_mock):
    # ...
    mock_object = unittest.mock.Mock(id=3)  # Or whatever id you need

    actual_email = Employee.set_email(mock_object)

    assert actual_email == expected_email
Sign up to request clarification or add additional context in comments.

1 Comment

That is what I was looking for! I went down the path of creating a separate dummy class but this is way better! Thank you for dealing with me in the comments!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.