首页 > 解决方案 > 模拟类和方法没有被修补

问题描述

我有一个文件 main.py,其中包含一个方法 main():

from grab_api_tokens import GrabApiTokens

def main()
    grab_api_tokens = GrabApiTokens(site_one, site_two)
    site_one_token = grab_api_tokens.login_to_site_one
    site_two_token = grab_api_tokens.login_to_site_two

在尝试对此进行测试时,我正在使用:

import unittest
from unittest.mock import patch, Mock
import main

class TestMain(unittest.TestCase):
@patch('main.grab_apitokens.GrabApiTokens.login_to_site_two')
@patch('main.grab_apitokens.GrabApiTokens.login_to_site_one')
@patch('main.grab_apitokens.GrabApiTokens')
def test_main(self, mock_grab_api_tokens, mock_login_to_site_one, mock_login_to_site_two):
    mock_grab_api_tokens = Mock(ok=True)
    mock_login_to_site_one.return_value = "fake_token_one"
    mock_login_to_site_two.return_value = "fake_token_two"
    main.main()
    self.assertTrue(mock_grab_api_tokens.called)

问题是,无论我如何更改@patch,我似乎都无法让 pycharm 识别模拟类。调用 main() 只是调用普通的 main 方法,它不会修补我指定的值。阅读单元测试文档后,我看不出哪里出错了。

标签: pythonpython-3.xunit-testingmockingpython-unittest

解决方案


您尝试修补的目标不正确。此外,您不需要修补GrabApiTokens类的属性。您可以修补GrabApiTokens类并将假数据直接分配给其实例的属性。

例如

main.py

from grab_api_tokens import GrabApiTokens


def main():
    site_one = '123'
    site_two = '456'
    grab_api_tokens = GrabApiTokens(site_one, site_two)
    site_one_token = grab_api_tokens.login_to_site_one
    site_two_token = grab_api_tokens.login_to_site_two
    print('site_one_token: ', site_one_token)
    print('site_two_token: ', site_two_token)

grab_api_tokens.py

class GrabApiTokens():
    def __init__(self, site_one, site_two) -> None:
        self.login_to_site_one = site_one
        self.login_to_site_two = site_two

test_main.py

import unittest
from unittest.mock import patch, Mock
import main


class TestMain(unittest.TestCase):
    @patch('main.GrabApiTokens')
    def test_main(self, mock_grab_api_tokens):
        mock_instance = mock_grab_api_tokens.return_value
        mock_instance.login_to_site_one = "fake_token_one"
        mock_instance.login_to_site_two = "fake_token_two"
        main.main()
        self.assertTrue(mock_grab_api_tokens.called)


if __name__ == '__main__':
    unittest.main()

测试结果:

 ⚡  coverage run /Users/dulin/workspace/github.com/mrdulin/python-codelab/src/stackoverflow/66641783/test_main.py && coverage report -m --include="src/*"
site_one_token:  fake_token_one
site_two_token:  fake_token_two
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
Name                                            Stmts   Miss  Cover   Missing
-----------------------------------------------------------------------------
src/stackoverflow/66641783/grab_api_tokens.py       4      2    50%   3-4
src/stackoverflow/66641783/main.py                  9      0   100%
src/stackoverflow/66641783/test_main.py            13      0   100%
-----------------------------------------------------------------------------
TOTAL 

推荐阅读