简体   繁体   中英

(Python) Mocking the return value of a method called inside another method

I have a class and a function:

class myclass(object):
    def get_info(self, big_string):
        string_that_always_exists = (big_string.split("Name: myname ")[1]).split("\n")[0]
        if "Name: " in big_string:
            result = self.find_details(string_that_always_exists)
            return result
        else:
            return None

    def find_details(string_that_always_exists):
        # sorts through huge string
        return dictionary_big

What I need to do is write a unit test that will patch the method find_details(string_that_always_exists) so it always equals the same dictionary.

I didn't even want to post what I've tried because I really don't understand how the unittest.test framework really works but I think it'll give some ideas:

@patch('myclass.find_details')
def test_get_info(self, mock_method):
    mock_method.return_value = Mock(myclass)
    mock_method.find_details.return_value = ["item 1", "item 2", "item 3", "item 4"]
    results = mock_method.get_info("big string with only one guaranteed sub string. Name: ")
    self.assertEqual(results[0], "item 1")

the above doesn't work. results always equals a MagicMock object, and not the return values are nowhere in results when I debug the program. I think its because I'm not specifying my patch correctly but honestly I don't know.

There are some problems with your test. First, I'm not sure if you are mocking the correct object, probaly you just don't show the real mock string. The mock string shall reference the object so that it can be imported, including the module name.

Second, you are not testing your class, but a mock. You should instantiate your real class and test that instead.

And third, you are setting the return_value in the wrong place. You already mock the function, so you just have to mock the return value of that function.

Last, your test would just return None , as your parameter does not contain "text", but probably this was not your real test. As a side note: it helps to provide real working code, even if it does not do what you want.

Your test could look something like this (assuming you class lives in mymodule.py ):

import unittest
from unittest.mock import patch

from mymodule import myclass

class TestMyClass(unittest.TestCase):
    @patch('mymodule.myclass.find_details')
    def test_get_info(self, mock_method):
        mock_method.return_value = ["item 1", "item 2", "item 3", "item 4"]
        cls = myclass()
        results = cls.get_info("Big string with text. Name: ")
        self.assertEqual(results[0], "item 1")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM