Test avec pytest
Bonjour j'ai de grosse difficulté pour écrire un test en python avec pytest.
Voila la méthode que je tente de tester :
def _set_mailbox_acl(self, dn: str, uid: str, user: str, acl: str):
try:
mb: Mailbox = Mailbox(name=uid, configuration=self._configuration)
new_uid = self._build_share_uid(uid_accessing=user, uid_shared=uid)
mb.update_acl(user=new_uid, acl=self._mce_acl_imap[acl])
_, msg = self.log_msg.set_mailbox_acl
self.logger.debug(
msg,
acl,
dn,
user,
uid,
)
except CYRUSError as err:
self._handle_cyrus_error(dn=dn, err=err)
Voila le test que j'ai écris :
def test_set_mailbox_acl(mock_treatments, mailbox_mock):
# Set up test data
dn = "test_dn"
uid = "test_uid"
user = "test_user"
acl = "read"
# Mock the necessary objects and methods
mock_treatments.mce_acl_imap = {
"read": "r",
"write": "w",
}
mock_treatments._set_mailbox_acl.mb = MagicMock()
mock_treatments.log_msg.set_mailbox_acl = (0, "msg")
new_uid = "mocker_uid"
mock_treatments._build_share_uid.return_value = new_uid
with patch("mce_sync.core.mailbox.Mailbox", return_value=mailbox_mock):
Treatments._set_mailbox_acl(mock_treatments, dn, uid, user, acl)
mailbox_mock.update_acl.assert_called_once_with(
user=new_uid,
acl=mock_treatments.mce_acl_imap,
)
Treatments.logger.debug.assert_called_once_with(
"msg",
acl,
dn,
user,
uid,
)
Voila l'erreur que j'ai :
mock_treatments = <mock id="140520282092304" spec="Treatments">, mailbox_mock = <mock id="140520285233552">
def test_set_mailbox_acl(mock_treatments, mailbox_mock):
# Set up test data
dn = "test_dn"
uid = "test_uid"
user = "test_user"
acl = "read"
# Mock the necessary objects and methods
mock_treatments.mce_acl_imap = {
"read": "r",
"write": "w",
}
mock_treatments._set_mailbox_acl.mb = MagicMock()
mock_treatments.log_msg.set_mailbox_acl = (0, "msg")
new_uid = "mocker_uid"
mock_treatments._build_share_uid.return_value = new_uid
# Utilisez patch pour remplacer la vraie classe Mailbox par le mock
with patch("mce_sync.core.mailbox.Mailbox", return_value=mailbox_mock):
# Appelez la méthode que vous voulez tester
> Treatments._set_mailbox_acl(mock_treatments, dn, uid, user, acl)
tests/treatments/unit/test_treatments.py:517:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
mce_sync/core/treatments.py:593: in _set_mailbox_acl
mb: Mailbox = Mailbox(name=uid, configuration=self._configuration)
mce_sync/core/mailbox/__init__.py:76: in __init__
self._imap = Cyrus(
mce_sync/core/cyrus/__init__.py:108: in __init__
self._session = CYRUS(url=self._url_server)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <cyruslibmce.src.cyrus.cyrus 0x7fcd6d7ca070="" at="" object="">, url = <mock id="140520281907504" name="mock._configuration.config.cyrus.uri">
def __init__(self, url="imap://localhost:143"):
self.VERBOSE = False
self.AUTH = False
self.ADMIN = None
self.AUSER = None
self.ADMINACL = "c"
self.SEP = DEFAULT_SEP
self.ENCODING = "imap"
self.NORMALIZE = False
self.LOGFD = stdout
> match = re_url.match(url)
E TypeError: expected string or bytes-like object
Je pense que le problème est que je n'arrive pas à Mock correctement la classe Mailbox. Je souhaiterai dans mon test mock la classe Mailbox pour que celle ci ne soit pas appeler par le test et ne tente pas de faire créer une classe CYRUS. Je veux juste vérifier que cette classe est appelé une fois. Je n'essaie pas pour le moment de tester si la Mailbox est bien créé.
Voila le code de la Mailbox au cas où :
class Mailbox:
def __init__(
self,
name: str,
configuration: ConfigLoader,
as_username: Optional[str] = None,
url_cyrus: Optional[str] = None,
) -> None:
self._configuration = configuration
self._url_cyrus = url_cyrus
self._as_username = as_username
self._imap = Cyrus(
configuration=self._configuration,
as_username=self._as_username,
url_cyrus=self._url_cyrus,
)
self._name = name
self._path = self._set_path()
self.logger = logging.getLogger("mce_sync.Mailbox")
self.log_msg = MailboxLogMsg()
def _set_path(self) -> str:
"""
Définie le chemin d'accès de la boite courante
Returns:
path
"""
path_root = self._configuration.config.mailbox.path_root
path_prefix = self._configuration.config.mailbox.path_prefix
path_suffix = self._configuration.config.mailbox.path_suffix
path = f"{path_root}" f"/{path_prefix}{self._name}{path_suffix}"
return path
def update_acl(self, user: str, acl: Optional[str]) -> None:
"""
Modifie les droits d'accès à un utilisateur sur la boite mail courante
Notes:
Si 'acl' est 'None' ou une chaine vide, les droits d'accès
sont retirés
Args:
user: str: utilisateur cible
acl: Optional[str]: nouveau droits d'accès
Returns:
None
Raises:
CYRUSError: En cas d'échec de transaction
"""
if acl is None or acl == "":
_, msg_success = self.log_msg.delete_acl_target
self.logger.debug(
msg_success,
self._path,
)
_, msg_success = self.log_msg.delete_acl
self.logger.debug(msg_success, user)
self._imap.remove_acl(mailbox=self._path, userid=user)
else:
self._imap.set_acl(mailbox=self._path, userid=user, acl=acl)
inbox_folders: List[
str
] = self._configuration.config.mailbox.inbox_folders
for mailbox in inbox_folders:
self._imap.set_acl(
mailbox=f"{self._path}/{mailbox}", userid=user, acl=acl
)
Merci d'avance pour votre aide !
Salut Flavien !
C'est toujours un peu difficile de déboguer des tests qui ne fonctionnent pas mais on va essayer ;)
Le problème est effectivement sur la génération d'un objet Cyrus car j'imagine qu'il n'a pas toutes les infos nécessaires pour le créer correctement et de toute façon tu ne veux pas créer un objet Cyrus qui semble nécessaire pour ton Mailbox si l'objectif est de faire un mock.
Du coup pour éviter ce problème il me semble qu'il faudrait que l'instance de Mailbox qui est retournée par ton mock ait déjà une propriété _imap configurée (pour éviter qu'elle ne tente d'instancier un objet CYRUS).
Tu peux rajouter un MagickMock comme ça :
mailbox_mock._imap = MagicMock() # On s'assure que _imap est déjà mocké
Essai déjà avec ça de voir si ça règle au moins ce problème spécifique :)
Bonjour Thibault, merci pour ta réponse !
Effectivement cela à réglé ce problème.
Mais finalement du à la dtructure particulière de cette app qui fait appel à des librairies externes qui n'ont pas de test, pour faire le travail de test unitaire correctement il faudrait écrire des tests pour les libs externes également. Mais par manque on a décidé d'abandonner les tests unitaires pour des tests end to end.
Inscris-toi
(c'est gratuit !)
Tu dois créer un compte pour participer aux discussions.
Créer un compte