2015-08-26 61 views
0

我想測試一個方法,無論它是否調用臨時內部對象的特定方法。 (ConfigParser.read)Python內部實體嘲諷

所以這個對象是在裏面創建的,並且在方法退出後它不能從外部訪問。

使用Python 2.7

在foobar.py

import ConfigParser 

class FooBar: 
    def method(self, filename): 
     config=ConfigParser.ConfigParser() 
     config.read(filename) 
     do_some_stuff() 

我想測試config.read是否被調用。

據我所知,修補程序修飾器是爲此設計的,但不幸的是,測試用例收到的MagicMock對象與內部創建的不一樣,並且我無法靠近方法內部的對象。

我想是這樣的:

class TestFooBar(TestCase): 

    def setUp(self): 
     self.myfoobar = FooBar() 

    @mock.patch('foobar.ConfigParser') 
    def test_read(self,mock_foobar): 
     self.myfoobar.method("configuration.ini") 
     assert mock_foobar.called # THIS IS OKAY 
     assert mock_foobar.read.called # THIS FAILS 
     mock_foobar.read.assert_called_with("configuration.ini") # FAILS TOO 

的問題是: - 在self.myfoobar.method創建之前內部ConfigReader mock_foobar創建。 - 當調試mock_foobar大約有以前的通話內部數據,但沒有(爲嘲諷的讀法內MagicMock)

當然,一條出路就是重構和給予.read()或「讀」屬性init()一個ConfigReader對象,但它並不總是可以改變代碼,我想在不接觸被測模塊的情況下掌握方法的內部對象。

回答

2

你太親近了!問題在於你在嘲笑這個類,但是接下來你的測試會檢查read()是否在這個模擬類上被調用 - 但是你實際上期待read()在你調用該類時返回的實例上被調用。下面的工作 - 我發現第二個測試比第一個更可讀,但它們都工作:

import ConfigParser 
from unittest import TestCase 

from mock import create_autospec, patch, Mock 


class FooBar(object): 
    def method(self, filename): 
     config=ConfigParser.ConfigParser() 
     config.read(filename) 


class TestFooBar(TestCase): 

    def setUp(self): 
     self.myfoobar = FooBar() 

    @patch('ConfigParser.ConfigParser') 
    def test_method(self, config_parser_class_mock): 
     config_parser_mock = config_parser_class_mock.return_value 

     self.myfoobar.method("configuration.ini") 

     config_parser_class_mock.assert_called_once_with() 
     config_parser_mock.read.assert_called_once_with("configuration.ini") 

    def test_method_better(self): 
     config_parser_mock = create_autospec(ConfigParser.ConfigParser, instance=True) 
     config_parser_class_mock = Mock(return_value=config_parser_mock) 

     with patch('ConfigParser.ConfigParser', config_parser_class_mock): 
      self.myfoobar.method("configuration.ini") 

     config_parser_class_mock.assert_called_once_with() 
     config_parser_mock.read.assert_called_once_with("configuration.ini") 
+0

謝謝!不幸的是,第一個不起作用(斷言AssertionError:預期的'read'被調用一次,被調用0次),第二個在「with @mock」行中有語法錯誤(也沒有「as something:」最後)。我沒有提到這是python 2.7,我會用這個信息更新這個問題。 – PetrosHu

+0

哦對不起,我看到你的導入是爲ConfigParser模塊而不是類。會相應更新。 –

+0

測試了新代碼併爲我工作 –