嘲笑整个班级

2024-05-10 09:12:22 发布

您现在位置:Python中文网/ 问答频道 /正文

长话短说,我完全可以模仿类方法,当它只是那个被mock对象替换的方法时,但是当我试图用mock对象替换整个类时,我无法模仿这个方法

@mock.patch.object成功地模拟了scan方法,但@mock.patch未能这样做。我以 https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch 但显然我做错了什么。在

在这两种情况下,我都在同一个命名空间中模拟lexicon模块(它是由import lexiconsentence_parser中导入的),但是mock_lexicon is lexicon.lexicon检查失败

#!python
import sys;
sys.path.append('D:\python\lexicon');
import lexicon;

import sentence_parser;
import unittest2 as unittest;
import mock;

class ParserTestCases(unittest.TestCase) :

    def setUp(self) :
        self.Parser = sentence_parser.Parser();

    @mock.patch('lexicon.lexicon')
    def test_categorizedWordsAreAssigned_v1(self, mock_lexicon) :

        print "mock is lexicon:";
        print mock_lexicon is lexicon.lexicon + "\n";

        instance = mock_lexicon.return_value;
        instance.scan.return_value = "anything";    

        self.Parser.categorize_words_in_sentence("sentence");
        instance.scan.assert_called_once_with("sentence");

    @mock.patch.object(lexicon.lexicon, 'scan')
    def test_categorizedWordsAreAssigned_v2(self, mock_scan) :

        mock_scan.return_value = "anything";    

        self.Parser.categorize_words_in_sentence("sentence");
        mock_scan.assert_called_once_with("sentence");

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

输出:

^{pr2}$

编辑:

为了澄清,Parser的定义如下

#!python

import sys;
sys.path.append('D:\python\lexicon');
import lexicon;

class Parser(object) :

    my_lexicon = lexicon.lexicon()

    def __init__(self) :
        self.categorized_words = ['test'];

    def categorize_words_in_sentence(self, sentence) :
        self.categorized_words = self.my_lexicon.scan(sentence);


if (__name__ == '__main__') :
    instance = Parser();
    instance.categorize_words_in_sentence("bear");
    print instance.categorized_words;

Tags: 方法instanceimportselfparserscandefsys
1条回答
网友
1楼 · 发布于 2024-05-10 09:12:22

这里真正相关的是categorize_words_in_sentenceParser的方法如何使用lexicon。但首先我们应该消除噪音:

print mock_lexicon is lexicon.lexicon + "\n"

是什么能把我们引向错误的方向:试着用

^{pr2}$

你会明白你在打印False,因为mock_lexicon不是{},而是{}。在

现在我无法告诉您为什么第一个测试不起作用,因为答案在categorize_words_in_sentence方法中,或者更可能在sentence_parser模块中,我可以猜到您可以有类似的

from lexicon import lexicon

在这两种情况下,请参阅Where to Patch文档,这些文档可以启发您了解问题的原因以及您在案例中真正需要修补的地方。在

第二个版本的工作仅仅是因为您正在修补对象而不是引用(这应该是不同的)。在

最后,更简洁和一般的版本可以是:

@mock.patch('lexicon.lexicon.scan', return_value="anything")
def test_categorizedWordsAreAssigned_v3(self, mock_scan) :
    self.Parser.categorize_words_in_sentence("sentence")
    mock_scan.assert_called_once_with("sentence")

还有一件事:删除unittest2至少你没有使用python2.4,而且你对后端口的unittest特性感兴趣。在

[编辑]

现在我可以停下来猜测并指出为什么第一个版本不起作用,也永远不会起作用:

class Parser(object) :
    my_lexicon = lexicon.lexicon()

Parser.my_lexicon属性在加载时间时计算。这意味着当您导入sentence_parser时,将创建一个lexicon,并且与{}相关联的引用。当您修补lexicon.lexicon时,这个引用保持不变,解析器对象仍然使用导入时创建的原始引用。在

您可以做的是修补Parser类中的引用

@patch("sentence_parser.Parser.my_lexicon")

如果您想给您的mock提供相同的lexicon签名,可以使用^{}。在

@patch("sentence_parser.Parser.my_lexicon", create_autospec("lexicon.lexicon", instance=True))

相关问题 更多 >