2015-08-26 2 views
0

Я хотел бы протестировать метод, вызвал ли он конкретный метод временного внутреннего объекта или нет. (ConfigParser.read)Внутренняя сущность Python mocking

Таким образом, объект создается внутри, и после выхода метода он не доступен снаружи.

Использование 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 

Проблема заключается в том: - mock_foobar создается перед self.myfoobar.method создает ConfigReader внутри. - при отладке mock_foobar не имеет внутренние данные о предыдущих вызовах, но не «читать» свойство (внутренний MagicMock для насмехаясь метод чтения)

Конечно один выход является рефакторинга и давая .read() или init() объект ConfigReader, но изменить код не всегда можно, и я хотел бы понять внутренние объекты метода, не касаясь тестируемого модуля.

ответ

2

Вы так близко! Проблема в том, что вы издеваетесь над классом, но тогда ваш тест проверяет, что read() вызывается в этом классе mock, но вы действительно ожидаете, что 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: Ожидаемое «чтение», которое вызывается один раз. Вызывается 0 раз.), Второй имеет синтаксическую ошибку в строке «with @mock» (также нет «как-то»: в конце). Я не упоминал, что это python 2.7, я обновлю эту информацию. – PetrosHu

+0

Ой, извините, я вижу, что ваш импорт предназначен для модуля ConfigParser, а не для класса. Будет соответствующим образом обновляться. –

+0

Протестировал новый код и работает для меня –

Смежные вопросы