[РЕДАКТИРОВАТЬ: проблема существует только с Python 2.7.С 3.7 работает как положено.Любая идея, в чем может быть разница, и если это возможно, чтобы она работала также с 2.7, который я должен использовать по некоторым причинам]
Я хочу переписать метод сокета sendto
, используя Mock.Мой первый подход был такой:
class TestClass01(TestCase):
@mock.patch.object(socket.socket, "sendto", new=mock_sendto)
def test_function1(self):
...
Однако это вызвало исключение:
AttributeError: '_socketobject' атрибут объекта 'sendto' доступен только для чтения.
Этот подход хорошо работал для других классов, но не для сокетов.Я так понимаю, причина в том, что __init__
вызывает setattr для всех функций-членов, например:
def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, _sock=None):
if _sock is None:
_sock = _realsocket(family, type, proto)
self._sock = _sock
for method in _delegate_methods:
setattr(self, method, getattr(_sock, method)) <<<<<<<<<<<<<
Затем я попробовал другой подход:
class TestClass01(TestCase):
@mock.patch("socket.socket")
def test_function1(self, mock_class):
s = mock.Mock(socket.socket)
s.sendto = mock_sendto
s.close = mock_close
mock_class.return_value = s
# ... run my tests here ...
args, kwargs = mock_class.call_args_list[0]
# Check arguments passed to sendto
Это работает, однако,Список аргументов вызова дает мне просто:
((2, 2), {})
Что соответствует конструктору AF_INET=2
и SOCK_DGRAM=2
.Там нет никаких следов моего звонка sendto
.Мой обходной путь - использование глобальных переменных, которые я установил из своей функции mock_sendto
.Хотя не очень элегантно.
У меня три вопроса:
- Могу ли я обойти проблему «только для чтения» и получить первоначальный подход к работе?
- Почему
all_args_list
отслеживает только вызов конструкции, но не sendto? - Есть ли лучший подход, чем использование глобальных переменных?
Заранее спасибо за вашеответы!