Это немного сложно, потому что я отлаживаю некоторый код, написанный долгое время за go в python 2.7
В процессе перехода на Python 3 (я знаю, я знаю) и сталкиваюсь с этой проблемой при попытке исправить юнит-тесты
Проблема в том, что я получаю ошибку TypeError: object() takes no parameters
Я перечислю функции ниже. Я должен заменить много имен функций и объектов. Если вы видите несоответствие в именах модулей, предположите, что это опечатка.
Сначала класс, который он вызывает
class Parser(object):
def __init__(self, some_instance, some_file):
self._some_instance = some_instance
self.stream = Parser.formsomestream(some_file)
self.errors = []
@staticmethod
def formsomestream(some_file):
# return a stream
class BetterParser(Parser):
def parse(self):
# skip some steps, shouldn't relate to the problem
return details # this is a string
class CSVUploadManager(object):
def __init__(self, model_instance, upload_file):
self._model_instance = model_instance
self._upload_file = upload_file
# then bunch of functions here
# then.....
def _parse(self):
parser_instance = self._parser_class(self._model_instance, self._upload_file)
self._csv_details = parser_instance.parse()
# bunch of stuff follows
def _validate(self):
if not self._parsed:
self._parse()
validator_instance = self._validator_class(self._model_instance, self._csv_details)
# some attributes to set up here
def is_valid(self):
if not self._validated:
self._validate()
Теперь тестовая функция откуда-то.to.this.validator импортирует MockUploadValidator из другого. place import CSVUploadManager
class TestSomething(SomeConfigsToBeMixedIn):
@mock.patch('path.to.BetterParser.parse')
@mock.patch('path.to.SomeValidator.__new__')
@mock.patch('path.to.SomeValidator.validate')
def test_validator_is_called(self, mock_validator_new, mock_parse):
mock_validator_new.return_value = MockUploadValidator.__new__(MockUploadValidator)
mock_parse.return_value = mock_csv_details
mock_validator_new.return_value = MockUploadValidator()
string_io = build_some_string_io_woohoo() # this returns a StringIO
some_file = get_temp_from_stream(string_io)
upload_manager = CSVUploadManager(a_model_instance, some_file)
upload_manager.is_valid() # this is where it fails and produces that error
self.assertTrue(mock_parse.called)
self.assertTrue(mock_validator_new.called)
validator_new_call_args = (SomeValidator, self.cash_activity, mock_csv_details)
self.assertEqual(mock_validator_new._mock_call_args_list[0][0], validator_new_call_args)
Как видите, CSVUploadManager принимает экземпляр модели django и файлоподобный объект obj, эта вещь вызовет self._parser_class
, который вызывает BetterParser
, затем BetterParser
делает свое дело.
Однако, я предполагаю, что это из-за насмешки, он возвращает TypeError: object() takes no parameters
Мои вопросы:
- Зачем это произошла ошибка?
- Почему происходит только на python 3.x? (Я использую 3.6)
- Это также приводит к сбою других тестов (в разных тестовых случаях), когда они обычно проходят, если я не тестирую их с неудачным тестом. Почему это так?
- Это действительно связано с издевательством? Я бы предположил, что это потому, что когда я тестирую на сервере, функциональность здесь.
РЕДАКТИРОВАТЬ: добавление трассировки
Traceback (most recent call last):
File "/path/to/lib/python3.6/site-packages/mock/mock.py", line 1305, in patched
return func(*args, **keywargs)
File "/path/to/test_file.py", line 39, in test_validator_is_called:
upload_manager.is_valid()
File "/path/to/manager.py", line 55, in is_valid
self._validate()
File "/path/to/manager.py", line 36, in _validate
validator_instance = self._validator_class(self._model_instance, self._csv_details)
TypeError: object() takes no parameters