У меня есть несколько классов шлюзов, которые обрабатывают взаимодействия с базой данных, например, один может выглядеть примерно так:
class ResourceGateway:
def __init__(self, redis_client):
self._redis = redis_client
self._redis_pipeline = None
def persist_resource(self, resource):
if self._redis_pipeline is None:
self._redis_pipeline = self._redis.pipeline()
self._redis_pipeline.zadd(resource['key'], resource, resource['score'])
def commit(self):
if self._redis_pipeline:
self._redis_pipeline.execute()
self._redis_pipeline = None
Если я хочу создать модульный тест для метода persist_resource, мне нужно проверить и посмотреть если функция zadd была вызвана с правильными атрибутами, верно? Может быть что-то вроде:
def test_persist_resource(mocker, redis_client, resource):
topic_gateway = ResourceGateway(redis_client)
topic_gateway.persist_resource(resource)
redis_client.pipeline.assert_called_once() # this I can test easily
topic_gateway._redis_pipeline.zadd.assert_called_once() # this I need to access protected attribute
ПРИМЕЧАНИЕ: я знаю, что это просто проверяет, что они вызываются один раз - позже я добавлю часть «вызываемый с».
Мой вопрос: так ли это "нормально", в этой ситуации, чтобы получить доступ к атрибуту private, чтобы сделать это утверждение?
Если нет, есть ли другой способ структурировать это? Этот вызов метода - последнее, что делает мое приложение до того, как чужой код вступает во владение - я не хочу тестировать что-либо за пределами этой точки, верно?
С одной стороны, это пахнет "побочным эффектом" «функции, и она должна быть как-то реструктурирована. С другой стороны, вызов базы данных почти всегда является побочным эффектом?
Я мог бы сделать атрибут конвейера доступным c, но для этого нет никаких причин, кроме как для теста.
Есть мысли, проблемы, советы?