Я придумал этот код:
Код: Выделить всё
from collections import deque
from threading import Lock
import socket
from time import sleep
from typing import Deque
import pytest
from pytest_mock import MockFixture
from comms import Comms
def mocked_socket(mocker: MockFixture):
connection = socket.socket()
backing_store: Deque[int] = deque()
lock = Lock()
def receiver(n: int):
with lock:
# NOTE: To better simulate socket behaviour, we allow the sender to refill the backing store for the duration of connection.timeout.
bl = len(backing_store)
if bl == 0 and connection.timeout is not None:
lock.release()
sleep(connection.timeout)
lock.acquire()
# FIXME: We raise a timeout here, even if connection.timeout is None (i.e. socket is blocking). This is, because returning an empty bytes object is interpreted as the other side having terminated the connection. If we wanted to model socket even more closely, we should have a condition variable for reception, that this thread can wait on.
bl = len(backing_store)
if bl == 0:
raise socket.timeout
n_cap = min(len(backing_store), n)
return bytes(backing_store.popleft() for _ in range(n_cap))
def sender(buffer: bytes):
with lock:
backing_store.extend(buffer)
mocker.patch.object(connection, "recv", wraps=receiver)
mocker.patch.object(connection, "sendall", wraps=sender)
return connection
def test(mocker: MockFixture):
connection = mocked_socket(mocker)
server = Comms(connection)
client = Comms(connection)
# ... whatever I want to test
Код: Выделить всё
self.temp_original = original
self.is_local = local
self._exit_stack = contextlib.ExitStack()
try:
> setattr(self.target, self.attribute, new_attr)
E AttributeError: 'socket' object attribute 'recv' is read-only
/usr/lib/python3.12/unittest/mock.py:1567: AttributeError
Код: Выделить всё
sendallЯ нашел Как имитировать свойство только для чтения с помощью макета?, но это только имеет дело с насмешливыми свойствами, а не методами.
Я никогда раньше не использовал pytest, unittest.mock и т. д., так есть ли простое решение, которое мне не хватает? Является ли то, что я пытаюсь сделать, правильным подходом?
Спасибо за вашу помощь.
Подробнее здесь: https://stackoverflow.com/questions/790 ... ytest-mock