From a6e02bdca60297bd5d24394a0b04629e6f6520ce Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Thu, 8 Dec 2022 17:06:58 +0100
Subject: [PATCH 4/7] toulouse-maelis: move referentials into db (#70982)

---
 .../migrations/0002_referential.py            |  43 +
 passerelle/contrib/toulouse_maelis/models.py  | 182 +++--
 .../R_read_category_list_2_items.xml          |  15 +
 tests/test_toulouse_maelis.py                 | 772 +++++++-----------
 4 files changed, 468 insertions(+), 544 deletions(-)
 create mode 100644 passerelle/contrib/toulouse_maelis/migrations/0002_referential.py
 create mode 100644 tests/data/toulouse_maelis/R_read_category_list_2_items.xml

diff --git a/passerelle/contrib/toulouse_maelis/migrations/0002_referential.py b/passerelle/contrib/toulouse_maelis/migrations/0002_referential.py
new file mode 100644
index 00000000..86dcae3e
--- /dev/null
+++ b/passerelle/contrib/toulouse_maelis/migrations/0002_referential.py
@@ -0,0 +1,43 @@
+# Generated by Django 2.2.26 on 2022-12-08 16:05
+
+import django.contrib.postgres.fields.jsonb
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('toulouse_maelis', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Referential',
+            fields=[
+                (
+                    'id',
+                    models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
+                ),
+                ('referential_name', models.CharField(max_length=64, verbose_name='Name')),
+                ('item_id', models.CharField(max_length=64, verbose_name='Key')),
+                ('item_text', models.CharField(max_length=128, verbose_name='Text')),
+                ('item_data', django.contrib.postgres.fields.jsonb.JSONField(verbose_name='Data')),
+                ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')),
+                ('updated', models.DateTimeField(auto_now=True, verbose_name='Updated')),
+                (
+                    'resource',
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        related_name='referential',
+                        to='toulouse_maelis.ToulouseMaelis',
+                        verbose_name='Resource',
+                    ),
+                ),
+            ],
+            options={
+                'ordering': ('referential_name', 'item_text', 'item_id'),
+                'unique_together': {('referential_name', 'item_id')},
+            },
+        ),
+    ]
diff --git a/passerelle/contrib/toulouse_maelis/models.py b/passerelle/contrib/toulouse_maelis/models.py
index 3d8cdfcd..3ad5038e 100644
--- a/passerelle/contrib/toulouse_maelis/models.py
+++ b/passerelle/contrib/toulouse_maelis/models.py
@@ -8,32 +8,35 @@
 # This program is distributed in the hope that it will be useful,
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 # GNU Affero General Public License for more details.
 #
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from operator import itemgetter
 from urllib.parse import urljoin
 
 import zeep
-from django.core.cache import cache
+from django.contrib.postgres.fields import JSONField
 from django.db import models
 from zeep.helpers import serialize_object
 from zeep.wsse.username import UsernameToken
 
 from passerelle.base.models import BaseResource, HTTPResource
 from passerelle.utils.api import endpoint
 from passerelle.utils.jsonresponse import APIError
 
 from . import schemas
 
 
+class UpdateError(Exception):
+    pass
+
+
 class ToulouseMaelis(BaseResource, HTTPResource):
     # noqa pylint: disable=too-many-public-methods
 
     base_wsdl_url = models.CharField(
         max_length=128,
         blank=False,
         verbose_name='URL de base des WSDL',
         default='https://demo-toulouse.sigec.fr/maelisws-toulouse/services/',
@@ -66,77 +69,112 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         except zeep.exceptions.Fault as e:
             raise APIError(e.message, err_code='%s-%s-%s' % (wsdl_short_name, service, e.code))
 
     def check_status(self):
         assert self.call('Family', 'isWSRunning')
         assert self.call('Activity', 'isWSRunning')
         assert self.call('Invoice', 'isWSRunning')
 
-    def get_referential(self, referential_name):
+    def update_referential(self, referential_name):
+        id_key, text_key = 'id', 'text'
 
         # local referentials
         if referential_name == 'Complement':
             response = [
                 {'id': 'B', 'text': 'bis'},
                 {'id': 'Q', 'text': 'quater'},
                 {'id': 'T', 'text': 'ter'},
             ]
-            return {'list': response, 'dict': {x['id']: x['text'] for x in response}}
         elif referential_name == 'Sex':
             response = [
                 {'id': 'F', 'text': 'Féminin'},
                 {'id': 'M', 'text': 'Masculin'},
             ]
-            return {'list': response, 'dict': {x['id']: x['text'] for x in response}}
-
-        # remote referentials
-        cache_key = 'maelis-%s-%s' % (self.pk, referential_name)
-        data = cache.get(cache_key)
-        if data is None:
-            response = self.call('Family', 'read' + referential_name + 'List')
-            data_list = []
+        else:
+            # remote referentials
+            try:
+                response = self.call('Family', 'read' + referential_name + 'List')
+                response = serialize_object(response)
+            except Exception as e:
+                raise UpdateError('Service indisponible : %s' % str(e))
             if referential_name == 'Organ':
-                data_list = [{'id': x.id, 'text': x.code} for x in response]
+                id_key, text_key = 'id', 'code'
             elif referential_name == 'Street':
-                data_list = [{'id': x.idStreet, 'text': x.libelleStreet} for x in response]
+                id_key, text_key = 'idStreet', 'libelleStreet'
             elif 'Indicator' in referential_name:
-                data_list = []
-                for item in serialize_object(response):
-                    item['id'] = item['code']
-                    item['text'] = item['label']
-                    data_list.append(item)
+                id_key, text_key = 'code', 'label'
             else:
-                data_list = [{'id': x.code, 'text': x.libelle} for x in response]
-
-            # sort list on text
-            data_list.sort(key=itemgetter('text', 'id'))
-
-            # remove redundant codes from list
-            uniq_text = set()
-            uniq_data = []
-            for item in data_list:
-                item['text'] = item['text'].strip()
-                if item['text'] not in uniq_text:
-                    uniq_data.append(item)
-                    uniq_text.add(item['text'])
-
-            data = {
-                'list': uniq_data,
-                'dict': {x['id']: x['text'] for x in data_list},
-            }
-            # put in cache for two hours
-            cache.set(cache_key, data, 3600 * 2)
-        return data
+                id_key, text_key = 'code', 'libelle'
+
+        try:
+            latest_update = (
+                self.referential.filter(referential_name=referential_name).latest('updated').updated
+            )
+        except Referential.DoesNotExist:
+            latest_update = None
+
+        for item in response:
+            text = item[text_key].strip()
+            self.referential.update_or_create(
+                resource_id=self.id,
+                referential_name=referential_name,
+                item_id=item[id_key],
+                defaults={
+                    'item_text': text,
+                    'item_data': dict({'id': item[id_key], 'text': text}, **item),
+                },
+            )
+
+        # clean item removed from referential
+        if latest_update is not None:
+            self.referential.filter(referential_name=referential_name, updated=latest_update).delete()
+
+    def update_referentials(self):
+        for name in (
+            'Category',
+            'ChildIndicator',
+            'Civility',
+            'Complement',
+            'Country',
+            'CSP',
+            'DietCode',
+            'Organ',
+            'PAI',
+            'Quality',
+            'Quotient',
+            'RLIndicator',
+            'Sex',
+            'Situation',
+            'Street',
+            'Vaccin',
+        ):
+            self.logger.info('Mise à jour du réferentiels %s' % name)
+            self.update_referential(name)
+
+    def daily(self):
+        try:
+            self.update_referentials()
+        except UpdateError as e:
+            self.logger.warning('Erreur sur la mise à jour: %s' % e)
+        else:
+            self.logger.info('Réferentiels mis à jour.')
+
+    def get_referential(self, referential_name):
+        return [
+            x.item_data
+            for x in self.referential.distinct('referential_name', 'item_text').filter(
+                referential_name=referential_name
+            )
+        ]
 
     def get_referential_value(self, referential_name, key):
         try:
-            return self.get_referential(referential_name)['dict'][key]
-        except KeyError:
-            # Maelis DB not properly configurated
+            return self.referential.get(referential_name=referential_name, item_id=key).item_text
+        except Referential.DoesNotExist:
             self.logger.warning("No '%s' key into Maelis '%s' referential", key, referential_name)
             return key
 
     def get_link(self, NameID):
         try:
             return self.link_set.get(name_id=NameID)
         except Link.DoesNotExist:
             raise APIError('User not linked to family', err_code='not-linked')
@@ -252,17 +290,19 @@ class ToulouseMaelis(BaseResource, HTTPResource):
         self.add_text_value_to_family(data)
         return data
 
     def assert_key_in_referential(self, referential_name, key_value, keys_text, required=True):
         if not key_value:
             if required:
                 raise APIError("%s is required and could not be None" % keys_text, err_code='field-required')
             return
-        if key_value not in self.get_referential(referential_name)['dict']:
+        try:
+            self.referential.get(referential_name=referential_name, item_id=key_value)
+        except Referential.DoesNotExist:
             ref_text = "required " if required else ""
             ref_text = ref_text + "referential"
             raise APIError(
                 "%s key value '%s' do not belong to '%s' %s"
                 % (keys_text, key_value, referential_name, ref_text),
                 err_code='wrong-key',
             )
 
@@ -368,152 +408,152 @@ class ToulouseMaelis(BaseResource, HTTPResource):
 
     @endpoint(
         display_category='Famille',
         description='Liste des catégories',
         name='read-category-list',
         perm='can_access',
     )
     def read_category_list(self, request):
-        return {'data': self.get_referential('Category')['list']}
+        return {'data': self.get_referential('Category')}
 
     @endpoint(
         display_category='Famille',
         description='Liste des indicateurs sur le enfants',
         name='read-child-indicator-list',
         perm='can_access',
     )
     def read_child_indicator_list(self, request):
-        return {'data': self.get_referential('ChildIndicator')['list']}
+        return {'data': self.get_referential('ChildIndicator')}
 
     @endpoint(
         display_category='Famille',
         description='Liste des civilités',
         name='read-civility-list',
         perm='can_access',
     )
     def read_civility_list(self, request):
-        return {'data': self.get_referential('Civility')['list']}
+        return {'data': self.get_referential('Civility')}
 
     @endpoint(
         display_category='Famille',
         description='Liste des compléments du numéro de voie',
         name='read-complement-list',
         perm='can_access',
     )
     def read_complement_list(self, request):
-        return {'data': self.get_referential('Complement')['list']}
+        return {'data': self.get_referential('Complement')}
 
     @endpoint(
         display_category='Famille',
         description='Liste des pays',
         name='read-country-list',
         perm='can_access',
     )
     def read_country_list(self, request):
-        return {'data': self.get_referential('Country')['list']}
+        return {'data': self.get_referential('Country')}
 
     @endpoint(
         display_category='Famille',
         description='liste des catégories socio-professionnelles',
         name='read-csp-list',
         perm='can_access',
     )
     def read_csp_list(self, request):
-        return {'data': self.get_referential('CSP')['list']}
+        return {'data': self.get_referential('CSP')}
 
     @endpoint(
         display_category='Famille',
         description='Liste des régimes alimentaires',
         name='read-dietcode-list',
         perm='can_access',
     )
     def read_dietcode_list(self, request):
-        return {'data': self.get_referential('DietCode')['list']}
+        return {'data': self.get_referential('DietCode')}
 
     @endpoint(
         display_category='Famille',
         description='Liste des organismes (CAF)',
         name='read-organ-list',
         perm='can_access',
     )
     def read_organ_list(self, request):
-        return {'data': self.get_referential('Organ')['list']}
+        return {'data': self.get_referential('Organ')}
 
     @endpoint(
         display_category='Famille',
         description="Liste des projet d'accueil individualisés",
         name='read-pai-list',
         perm='can_access',
     )
     def read_pai_list(self, request):
-        return {'data': self.get_referential('PAI')['list']}
+        return {'data': self.get_referential('PAI')}
 
     @endpoint(
         display_category='Famille',
         description='liste des qualités du référenciel',
         name='read-quality-list',
         perm='can_access',
     )
     def read_quality_list(self, request):
-        return {'data': self.get_referential('Quality')['list']}
+        return {'data': self.get_referential('Quality')}
 
     @endpoint(
         display_category='Famille',
         description='Liste des quotients',
         name='read-quotient-list',
         perm='can_access',
     )
     def read_quotient_list(self, request):
-        return {'data': self.get_referential('Quotient')['list']}
+        return {'data': self.get_referential('Quotient')}
 
     @endpoint(
         display_category='Famille',
         description='Liste des indicateurs sur les responsables légaux',
         name='read-rl-indicator-list',
         perm='can_access',
     )
     def read_rl_indicator_list(self, request):
-        return {'data': self.get_referential('RLIndicator')['list']}
+        return {'data': self.get_referential('RLIndicator')}
 
     @endpoint(
         display_category='Famille',
         description='Liste des sexes',
         name='read-sex-list',
         perm='can_access',
     )
     def read_sex_list(self, request):
-        return {'data': self.get_referential('Sex')['list']}
+        return {'data': self.get_referential('Sex')}
 
     @endpoint(
         display_category='Famille',
         description='liste des situations',
         name='read-situation-list',
         perm='can_access',
     )
     def read_situation_list(self, request):
-        return {'data': self.get_referential('Situation')['list']}
+        return {'data': self.get_referential('Situation')}
 
     @endpoint(
         display_category='Famille',
         description='liste des voies',
         name='read-street-list',
         perm='can_access',
     )
     def read_street_list(self, request):
-        return {'data': self.get_referential('Street')['list']}
+        return {'data': self.get_referential('Street')}
 
     @endpoint(
         display_category='Famille',
         description='Liste des vaccins',
         name='read-vaccin-list',
         perm='can_access',
     )
     def read_vaccin_list(self, request):
-        return {'data': self.get_referential('Vaccin')['list']}
+        return {'data': self.get_referential('Vaccin')}
 
     @endpoint(
         display_category='Famille',
         description='Lier un compte usager à une famille',
         perm='can_access',
         parameters={'NameID': {'description': 'Publik NameID'}},
         post={'request_body': {'schema': {'application/json': schemas.LINK_SCHEMA}}},
     )
@@ -1165,8 +1205,30 @@ class Link(models.Model):
     resource = models.ForeignKey(ToulouseMaelis, on_delete=models.CASCADE)
     name_id = models.CharField(blank=False, max_length=256)
     family_id = models.CharField(blank=False, max_length=128)
     created = models.DateTimeField(auto_now_add=True)
     updated = models.DateTimeField(auto_now=True)
 
     class Meta:
         unique_together = ('resource', 'name_id')
+
+
+class Referential(models.Model):
+    resource = models.ForeignKey(
+        verbose_name='Resource',
+        to=ToulouseMaelis,
+        on_delete=models.CASCADE,
+        related_name='referential',
+    )
+    referential_name = models.CharField('Name', max_length=64)
+    item_id = models.CharField('Key', max_length=64)
+    item_text = models.CharField('Text', max_length=128)
+    item_data = JSONField('Data')
+    created = models.DateTimeField('Created', auto_now_add=True)
+    updated = models.DateTimeField('Updated', auto_now=True)
+
+    def __repr__(self):
+        return '<Referential "%s/%s">' % (self.referential_name, self.item_id)
+
+    class Meta:
+        ordering = ('referential_name', 'item_text', 'item_id')
+        unique_together = [['referential_name', 'item_id']]
diff --git a/tests/data/toulouse_maelis/R_read_category_list_2_items.xml b/tests/data/toulouse_maelis/R_read_category_list_2_items.xml
new file mode 100644
index 00000000..ffb81ecd
--- /dev/null
+++ b/tests/data/toulouse_maelis/R_read_category_list_2_items.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
+  <soap:Body>
+    <ns2:readCategoryListResponse xmlns:ns2="family.ws.maelis.sigec.com">
+      <itemList>
+        <code>BI</code>
+        <libelle>BIPARENTALE</libelle>
+      </itemList>
+      <itemList>
+        <code>ACCEUI</code>
+        <libelle>Famille acceuillante</libelle>
+      </itemList>
+    </ns2:readCategoryListResponse>
+  </soap:Body>
+</soap:Envelope>
diff --git a/tests/test_toulouse_maelis.py b/tests/test_toulouse_maelis.py
index 0907c98f..3f5556ca 100644
--- a/tests/test_toulouse_maelis.py
+++ b/tests/test_toulouse_maelis.py
@@ -16,17 +16,17 @@
 import logging
 import os
 from unittest import mock
 
 import pytest
 from lxml import etree
 from requests.exceptions import ConnectionError
 
-from passerelle.contrib.toulouse_maelis.models import Link, ToulouseMaelis
+from passerelle.contrib.toulouse_maelis.models import Link, Referential, ToulouseMaelis
 from passerelle.utils.jsonresponse import APIError
 from passerelle.utils.soap import SOAPError
 from tests.utils import FakedResponse, generic_endpoint_url, setup_access_rights
 
 TEST_BASE_DIR = os.path.join(os.path.dirname(__file__), 'data', 'toulouse_maelis')
 
 
 def get_xml_file(filename):
@@ -40,30 +40,16 @@ ACTIVITY_SERVICE_WSDL = FakedResponse(content=get_xml_file('ActivityService.wsdl
 INVOICE_SERVICE_WSDL = FakedResponse(content=get_xml_file('InvoiceService.wsdl'), status_code=200)
 FAILED_AUTH = FakedResponse(content=get_xml_file('R_failed_authentication.xml'), status_code=500)
 ISWSRUNNING_TRUE = FakedResponse(content=get_xml_file('R_is_ws_running.xml') % b'true', status_code=200)
 ISWSRUNNING_FALSE = FakedResponse(content=get_xml_file('R_is_ws_running.xml') % b'false', status_code=200)
 READ_FAMILY = FakedResponse(content=get_xml_file('R_read_family.xml'), status_code=200)
 READ_FAMILY_LAX = FakedResponse(content=get_xml_file('R_read_family_relax.xml'), status_code=200)
 READ_FAMILY_ORD = FakedResponse(content=get_xml_file('R_read_family_reordered.xml'), status_code=200)
 READ_RL1_FAMILY = FakedResponse(content=get_xml_file('R_read_family_with_only_rl1.xml'), status_code=200)
-READ_CATEGORIES = FakedResponse(content=get_xml_file('R_read_category_list.xml'), status_code=200)
-READ_CHILD_INDICATOR = FakedResponse(content=get_xml_file('R_read_child_indicator_list.xml'), status_code=200)
-READ_CIVILITIES = FakedResponse(content=get_xml_file('R_read_civility_list.xml'), status_code=200)
-READ_COUNTRY = FakedResponse(content=get_xml_file('R_read_country_list.xml'), status_code=200)
-READ_CSP = FakedResponse(content=get_xml_file('R_read_csp_list.xml'), status_code=200)
-READ_DIETCODE = FakedResponse(content=get_xml_file('R_read_dietcode_list.xml'), status_code=200)
-READ_ORGAN = FakedResponse(content=get_xml_file('R_read_organ_list.xml'), status_code=200)
-READ_PAI = FakedResponse(content=get_xml_file('R_read_pai_list.xml'), status_code=200)
-READ_QUALITIES = FakedResponse(content=get_xml_file('R_read_quality_list.xml'), status_code=200)
-READ_QUOTIENT = FakedResponse(content=get_xml_file('R_read_quotient_list.xml'), status_code=200)
-READ_RL_INDICATOR = FakedResponse(content=get_xml_file('R_read_rl_indicator_list.xml'), status_code=200)
-READ_SITUATIONS = FakedResponse(content=get_xml_file('R_read_situation_list.xml'), status_code=200)
-READ_STREET = FakedResponse(content=get_xml_file('R_read_street_list.xml'), status_code=200)
-READ_VACCIN = FakedResponse(content=get_xml_file('R_read_vaccin_list.xml'), status_code=200)
 IS_RL_EXISTS_TRUE = FakedResponse(content=get_xml_file('R_is_rl_exists.xml') % b'true', status_code=200)
 IS_RL_EXISTS_FALSE = FakedResponse(content=get_xml_file('R_is_rl_exists.xml') % b'false', status_code=200)
 IS_CHILD_EXISTS_TRUE = FakedResponse(content=get_xml_file('R_is_child_exists.xml') % b'true', status_code=200)
 IS_CHILD_EXISTS_FALSE = FakedResponse(
     content=get_xml_file('R_is_child_exists.xml') % b'false', status_code=200
 )
 CREATE_FAMILY = FakedResponse(content=get_xml_file('R_create_family.xml'), status_code=200)
 CREATE_FAMILY_ERR = FakedResponse(content=get_xml_file('R_create_family_error.xml'), status_code=200)
@@ -100,16 +86,44 @@ def con(db):
         ToulouseMaelis.objects.create(
             slug='test',
             zeep_wsse_username='maelis-webservice',
             zeep_wsse_password='maelis-password',
         )
     )
 
 
+@pytest.fixture
+def ref(con, caplog):
+    mocked_get = mock.patch('passerelle.utils.Request.get', return_value=FAMILY_SERVICE_WSDL)
+    mocked_post = mock.patch(
+        'passerelle.utils.Request.post',
+        side_effect=[
+            FakedResponse(content=get_xml_file('R_read_category_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_child_indicator_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_civility_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_country_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_csp_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_dietcode_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_organ_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_pai_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_quality_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_quotient_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_rl_indicator_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_situation_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_street_list.xml'), status_code=200),
+            FakedResponse(content=get_xml_file('R_read_vaccin_list.xml'), status_code=200),
+        ],
+    )
+    mocked_get.start()
+    mocked_post.start()
+    con.daily()
+    assert caplog.messages[-1] == 'Réferentiels mis à jour.'
+
+
 @mock.patch('passerelle.utils.Request.get')
 def test_call_with_wrong_wsdl_url(mocked_get, con):
     mocked_get.side_effect = CONNECTION_ERROR
     with pytest.raises(
         SOAPError,
         match='cannot be loaded: No address associated with hostname',
     ) as e:
         con.call('Family', 'isWSRunning')
@@ -201,16 +215,62 @@ def test_replace_null_values(con):
             'street1': 'Chateau',
             'street2': '',
             'town': 'Paris',
             'zipcode': '75014',
         }
     }
 
 
+@mock.patch('passerelle.utils.Request.get')
+def test_update_referential(mocked_get, con):
+    mocked_get.return_value = FAMILY_SERVICE_WSDL
+
+    with mock.patch('passerelle.utils.Request.post') as mocked_post:
+        mocked_post.return_value = FakedResponse(
+            content=get_xml_file('R_read_category_list.xml'), status_code=200
+        )
+        con.update_referential('Category')
+        assert [
+            (x.item_id, x.item_text) for x in Referential.objects.filter(referential_name='Category')
+        ] == [('BI', 'BIPARENTALE'), ('ACCEUI', "FAMILLE D'ACCUEIL"), ('MONO', 'MONOPARENTALE')]
+
+    with mock.patch('passerelle.utils.Request.post') as mocked_post:
+        mocked_post.return_value = FakedResponse(
+            content=get_xml_file('R_read_category_list_2_items.xml'), status_code=200
+        )
+        con.update_referential('Category')
+        assert [
+            (x.item_id, x.item_text) for x in Referential.objects.filter(referential_name='Category')
+        ] == [('BI', 'BIPARENTALE'), ('ACCEUI', 'Famille acceuillante')]
+
+
+def test_cron(ref):
+    assert Referential.objects.filter(referential_name='Category').count() == 3
+    assert sorted(list({x.referential_name for x in Referential.objects.all()})) == [
+        'CSP',
+        'Category',
+        'ChildIndicator',
+        'Civility',
+        'Complement',
+        'Country',
+        'DietCode',
+        'Organ',
+        'PAI',
+        'Quality',
+        'Quotient',
+        'RLIndicator',
+        'Sex',
+        'Situation',
+        'Street',
+        'Vaccin',
+    ]
+    assert Referential.objects.count() == 230
+
+
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
 def test_link(mocked_post, mocked_get, con, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.return_value = READ_FAMILY
     url = get_endpoint('link')
     assert Link.objects.count() == 0
 
@@ -256,96 +316,63 @@ def test_unlink(con, app):
     assert resp.json['err'] == 0
     assert resp.json['data'] == 'ok'
 
     resp = app.post_json(url + '?NameID=local')
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_get_referential_using_cache(mocked_post, mocked_get, con, freezer):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_CATEGORIES
-
-    freezer.move_to('2021-11-10 00:00')
-    con.get_referential('Category')
-    assert mocked_post.call_count == 1
-
-    con.get_referential('Category')
-    assert mocked_post.call_count == 1
-
-    freezer.move_to('2021-11-10 02:00')
-    con.get_referential('Category')
-    assert mocked_post.call_count == 2
-
+def test_get_referential(con, ref):
+    assert con.get_referential('Category') == [
+        {'code': 'BI', 'id': 'BI', 'libelle': 'BIPARENTALE', 'text': 'BIPARENTALE'},
+        {'code': 'ACCEUI', 'id': 'ACCEUI', 'libelle': "FAMILLE D'ACCUEIL", 'text': "FAMILLE D'ACCUEIL"},
+        {'code': 'MONO', 'id': 'MONO', 'libelle': 'MONOPARENTALE', 'text': 'MONOPARENTALE'},
+    ]
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_get_referential_value(mocked_post, mocked_get, con):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_CSP
 
+def test_get_referential_value(con, ref):
     assert con.get_referential_value('CSP', '1') == 'AGRICULTEUR'
     assert con.get_referential_value('CSP', 'AGR') == 'AGRICULTEUR'
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_get_referential_value_not_found(mocked_post, mocked_get, con, caplog):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_CIVILITIES
-
+def test_get_referential_value_not_found(con, ref, caplog):
     assert con.get_referential_value('Civility', 'MR') == 'MR'
     assert len(caplog.records) == 1
     assert caplog.records[0].levelno == logging.WARNING
     assert caplog.records[0].message == "No 'MR' key into Maelis 'Civility' referential"
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_category_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_CATEGORIES
+def test_read_category_list(con, ref, app):
     url = get_endpoint('read-category-list')
 
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert resp.json['data'] == [
-        {'id': 'BI', 'text': 'BIPARENTALE'},
-        {'id': 'ACCEUI', 'text': "FAMILLE D'ACCUEIL"},
-        {'id': 'MONO', 'text': 'MONOPARENTALE'},
+        {'id': 'BI', 'text': 'BIPARENTALE', 'code': 'BI', 'libelle': 'BIPARENTALE'},
+        {'id': 'ACCEUI', 'text': "FAMILLE D'ACCUEIL", 'code': 'ACCEUI', 'libelle': "FAMILLE D'ACCUEIL"},
+        {'id': 'MONO', 'text': 'MONOPARENTALE', 'code': 'MONO', 'libelle': 'MONOPARENTALE'},
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_country_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_COUNTRY
+def test_read_country_list(con, ref, app):
     url = get_endpoint('read-country-list')
 
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert len(resp.json['data']) == 3
     assert resp.json['data'] == [
-        {'id': '212', 'text': 'AFGHANISTAN'},
-        {'id': '303', 'text': 'AFRIQUE DU SUD'},
-        {'id': '125', 'text': 'ALBANIE'},
+        {'id': '212', 'code': '212', 'text': 'AFGHANISTAN', 'libelle': 'AFGHANISTAN'},
+        {'id': '303', 'code': '303', 'text': 'AFRIQUE DU SUD', 'libelle': 'AFRIQUE DU SUD'},
+        {'id': '125', 'code': '125', 'text': 'ALBANIE', 'libelle': 'ALBANIE'},
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_child_indicator_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_CHILD_INDICATOR
+def test_read_child_indicator_list(con, ref, app):
     url = get_endpoint('read-child-indicator-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert len(resp.json['data']) == 8
     assert resp.json['data'][0:2] == [
         {
             'id': 'AUTRE',
             'text': 'Autre',
             'choiceList': [],
@@ -359,196 +386,131 @@ def test_read_child_indicator_list(mocked_post, mocked_get, con, app):
             'choiceList': [],
             'code': 'AVL',
             'label': 'Auxiliaire de Vie loisirs',
             'typeDesc': 'NONE',
         },
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_civility_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_CIVILITIES
+def test_read_civility_list(con, ref, app):
     url = get_endpoint('read-civility-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert resp.json['data'] == [
-        {"id": "MME", "text": "Madame"},
-        {"id": "M.", "text": "Monsieur"},
+        {'id': 'MME', 'code': 'MME', 'text': 'Madame', 'libelle': 'Madame'},
+        {'id': 'M.', 'code': 'M.', 'text': 'Monsieur', 'libelle': 'Monsieur'},
     ]
 
 
-def test_read_complement_list(con, app):
+def test_read_complement_list(con, ref, app):
     url = get_endpoint('read-complement-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert resp.json['data'] == [
         {'id': 'B', 'text': 'bis'},
         {'id': 'Q', 'text': 'quater'},
         {'id': 'T', 'text': 'ter'},
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_csp_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_CSP
+def test_read_csp_list(con, ref, app):
     url = get_endpoint('read-csp-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
-    assert resp.json['data'] == [
-        {'id': '14', 'text': 'AGENT DE MAITRISE'},
-        {'id': '1', 'text': 'AGRICULTEUR'},
-        {'id': 'ART', 'text': 'ARTISAN'},
-        {'id': '2', 'text': 'ARTISAN-COMMERCANT'},
-        {'id': '15', 'text': 'AUTRES'},
-        {'id': '4', 'text': 'CADRE'},
-        {'id': '13', 'text': 'CADRE SUPERIEUR'},
-        {'id': '3', 'text': "CHEF D'ENTREPRISE"},
-        {'id': 'CHOM', 'text': 'CHOMEUR'},
-        {'id': '7', 'text': 'COMMERCANT'},
-        {'id': '10', 'text': "DEMANDEUR D'EMPLOI"},
-        {'id': 'DIV', 'text': 'DIVERS'},
-        {'id': '5', 'text': 'EMPLOYE'},
-        {'id': '17', 'text': 'ENSEIGNANT'},
-        {'id': '8', 'text': 'ETUDIANT'},
-        {'id': '11', 'text': 'FONCTIONNAIRE'},
-        {'id': 'MAIR', 'text': 'MAIRIE DE NICE'},
-        {'id': '6', 'text': 'OUVRIER'},
-        {'id': 'PERENS', 'text': 'PERISCO ENSEIGNANT'},
-        {'id': 'PEREXT', 'text': 'PERISCO EXTERNE'},
-        {'id': 'PERMAI', 'text': 'PERISCO MAIRIE DE NICE'},
-        {'id': 'PERANI', 'text': 'PERISCO S.ANIMATION'},
-        {'id': '9', 'text': 'PROFESSION LIBERALE'},
-        {'id': '12', 'text': 'RETRAITE'},
-        {'id': 'RMI', 'text': "REVENU MINIMUM D'INSERTION"},
-        {'id': '16', 'text': 'SANS PROFESSION'},
-        {'id': 'SEC', 'text': 'SECRETAIRE'},
+    assert resp.json['data'][:5] == [
+        {'code': '14', 'id': '14', 'libelle': 'AGENT DE MAITRISE', 'text': 'AGENT DE MAITRISE'},
+        {'code': '1', 'id': '1', 'libelle': 'AGRICULTEUR', 'text': 'AGRICULTEUR'},
+        {'code': 'ART', 'id': 'ART', 'libelle': 'ARTISAN', 'text': 'ARTISAN'},
+        {'code': '2', 'id': '2', 'libelle': 'ARTISAN-COMMERCANT', 'text': 'ARTISAN-COMMERCANT'},
+        {'code': '15', 'id': '15', 'libelle': 'AUTRES', 'text': 'AUTRES'},
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_dietcode_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_DIETCODE
+def test_read_dietcode_list(con, ref, app):
     url = get_endpoint('read-dietcode-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert resp.json['data'] == [
-        {'id': 'STD', 'text': '1- REPAS STANDARD'},
-        {'id': 'RSP', 'text': '2- RÉGIME SANS PORC'},
-        {'id': 'RSV', 'text': '3- RÉGIME SANS VIANDE'},
-        {'id': 'PAI', 'text': "4- PROTOCOLE D'ACCUEIL INDIVIDUALISÉ"},
-        {'id': 'BB', 'text': 'REPAS BEBE'},
-        {'id': 'MSP', 'text': 'REPAS MOYEN SANS PORC'},
-        {'id': 'MSV', 'text': 'REPAS MOYEN SANS VIANDE'},
-        {'id': 'MST', 'text': 'REPAS MOYEN STANDARD'},
+        {'id': 'STD', 'code': 'STD', 'text': '1- REPAS STANDARD', 'libelle': '1- REPAS STANDARD'},
+        {'id': 'RSP', 'code': 'RSP', 'text': '2- RÉGIME SANS PORC', 'libelle': '2- RÉGIME SANS PORC'},
+        {'id': 'RSV', 'code': 'RSV', 'text': '3- RÉGIME SANS VIANDE', 'libelle': '3- RÉGIME SANS VIANDE'},
+        {
+            'id': 'PAI',
+            'code': 'PAI',
+            'text': "4- PROTOCOLE D'ACCUEIL INDIVIDUALISÉ",
+            'libelle': "4- PROTOCOLE D'ACCUEIL INDIVIDUALISÉ",
+        },
+        {'id': 'BB', 'code': 'BB', 'text': 'REPAS BEBE', 'libelle': 'REPAS BEBE'},
+        {'id': 'MSP', 'code': 'MSP', 'text': 'REPAS MOYEN SANS PORC', 'libelle': 'REPAS MOYEN SANS PORC'},
+        {'id': 'MSV', 'code': 'MSV', 'text': 'REPAS MOYEN SANS VIANDE', 'libelle': 'REPAS MOYEN SANS VIANDE'},
+        {'id': 'MST', 'code': 'MST', 'text': 'REPAS MOYEN STANDARD', 'libelle': 'REPAS MOYEN STANDARD'},
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_organ_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_ORGAN
+def test_read_organ_list(con, ref, app):
     url = get_endpoint('read-organ-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert len(resp.json['data']) == 92
     assert resp.json['data'][:5] == [
-        {'id': 'A10000979374', 'text': 'ALC L OLIVIER'},
-        {'id': 'A10000979372', 'text': 'ALVA 06'},
-        {'id': 'A10000980566', 'text': 'ANTIBES'},
-        {'id': 'A10000980388', 'text': 'APAJH'},
-        {'id': 'A10016401771', 'text': 'ASCROS'},
+        {'id': 'A10000979374', 'code': 'ALC L OLIVIER', 'text': 'ALC L OLIVIER', 'libelle': None},
+        {'id': 'A10000979372', 'code': 'ALVA 06', 'text': 'ALVA 06', 'libelle': None},
+        {'id': 'A10000980566', 'code': 'ANTIBES', 'text': 'ANTIBES', 'libelle': None},
+        {'id': 'A10000980388', 'code': 'APAJH', 'text': 'APAJH', 'libelle': None},
+        {'id': 'A10016401771', 'code': 'ASCROS', 'text': 'ASCROS', 'libelle': None},
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_pai_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_PAI
+def test_read_pai_list(con, ref, app):
     url = get_endpoint('read-pai-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert resp.json['data'] == [
-        {'id': 'PAIALI', 'text': 'ALIMENTAIRE'},
-        {'id': 'PAIO', 'text': 'AUTRE'},
-        {'id': 'PAIMED', 'text': 'MEDICAL'},
-        {'id': 'PAI2', 'text': 'MEDICAL ET ALIMENTAIRE'},
+        {'id': 'PAIALI', 'code': 'PAIALI', 'text': 'ALIMENTAIRE', 'libelle': 'ALIMENTAIRE'},
+        {'id': 'PAIO', 'code': 'PAIO', 'text': 'AUTRE', 'libelle': 'AUTRE'},
+        {'id': 'PAIMED', 'code': 'PAIMED', 'text': 'MEDICAL', 'libelle': 'MEDICAL'},
+        {'id': 'PAI2', 'code': 'PAI2', 'text': 'MEDICAL ET ALIMENTAIRE', 'libelle': 'MEDICAL ET ALIMENTAIRE'},
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_quality_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_QUALITIES
+def test_read_quality_list(con, ref, app):
     url = get_endpoint('read-quality-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
-    assert resp.json['data'] == [
-        {'id': 'AU', 'text': 'AUTRE'},
-        {'id': 'BP', 'text': 'BEAU PERE'},
-        {'id': 'BM', 'text': 'BELLE MERE'},
-        {'id': 'CONSO', 'text': 'CONSOMMATEUR'},
-        {'id': 'EN', 'text': 'ENFANT'},
-        {'id': 'FS', 'text': 'FRERES ET SOEURS'},
-        {'id': 'GM', 'text': 'GRAND MERE MATERNELLE'},
-        {'id': 'GP', 'text': 'GRAND PERE MATERNEL'},
-        {'id': 'GMP', 'text': 'GRAND-MERE PATERNELLE'},
-        {'id': 'GPP', 'text': 'GRAND-PERE PATERNEL'},
-        {'id': 'MAIRIE', 'text': 'MAIRIE'},
-        {'id': 'MERE', 'text': 'MERE'},
-        {'id': 'O', 'text': 'ONCLE'},
-        {'id': 'OS', 'text': 'ORGANISME SOCIAL'},
-        {'id': 'PERE', 'text': 'PERE'},
-        {'id': 'T', 'text': 'TANTE'},
-        {'id': 'TUTEUR', 'text': 'TUTEUR'},
+    assert resp.json['data'][:5] == [
+        {'id': 'AU', 'code': 'AU', 'text': 'AUTRE', 'libelle': 'AUTRE'},
+        {'id': 'BP', 'code': 'BP', 'text': 'BEAU PERE', 'libelle': 'BEAU PERE'},
+        {'id': 'BM', 'code': 'BM', 'text': 'BELLE MERE', 'libelle': 'BELLE MERE'},
+        {'id': 'CONSO', 'code': 'CONSO', 'text': 'CONSOMMATEUR', 'libelle': 'CONSOMMATEUR'},
+        {'id': 'EN', 'code': 'EN', 'text': 'ENFANT', 'libelle': 'ENFANT'},
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_quotient_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_QUOTIENT
+def test_read_quotient_list(con, ref, app):
     url = get_endpoint('read-quotient-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert resp.json['data'] == [
-        {'id': 'QF', 'text': 'GRILLE DE QUOTIENT'},
-        {'id': 'QCLSH', 'text': 'QUOTIENT CENTRE AERE'},
-        {'id': 'QJEU', 'text': 'QUOTIENT JEUNESSE'},
-        {'id': 'QS', 'text': 'QUOTIENT SCOLAIRE'},
-        {'id': 'QSPORT', 'text': 'QUOTIENT SPORT'},
-        {'id': 'MOY ECO', 'text': 'REVENU MOYEN ( MENSUEL OU ANNUEL)'},
+        {'id': 'QF', 'code': 'QF', 'text': 'GRILLE DE QUOTIENT', 'libelle': 'GRILLE DE QUOTIENT'},
+        {'id': 'QCLSH', 'code': 'QCLSH', 'text': 'QUOTIENT CENTRE AERE', 'libelle': 'QUOTIENT CENTRE AERE'},
+        {'id': 'QJEU', 'code': 'QJEU', 'text': 'QUOTIENT JEUNESSE', 'libelle': 'QUOTIENT JEUNESSE'},
+        {'id': 'QS', 'code': 'QS', 'text': 'QUOTIENT SCOLAIRE', 'libelle': 'QUOTIENT SCOLAIRE'},
+        {'id': 'QSPORT', 'code': 'QSPORT', 'text': 'QUOTIENT SPORT', 'libelle': 'QUOTIENT SPORT'},
+        {
+            'id': 'MOY ECO',
+            'code': 'MOY ECO',
+            'text': 'REVENU MOYEN ( MENSUEL OU ANNUEL)',
+            'libelle': 'REVENU MOYEN ( MENSUEL OU ANNUEL)',
+        },
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_rl_indicator_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_RL_INDICATOR
+def test_read_rl_indicator_list(con, ref, app):
     url = get_endpoint('read-rl-indicator-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert len(resp.json['data']) == 4
     assert resp.json['data'][1:3] == [
         {
             'id': 'AVS',
             'text': 'Auxiliaire de Vie scolaire',
             'choiceList': [],
@@ -562,101 +524,92 @@ def test_read_rl_indicator_list(mocked_post, mocked_get, con, app):
             'choiceList': [],
             'code': 'ETABSPEC',
             'label': 'Etablissement spécialisé',
             'typeDesc': 'NOTE',
         },
     ]
 
 
-def test_read_sex_list(con, app):
+def test_read_sex_list(con, app, ref):
     url = get_endpoint('read-sex-list')
 
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert resp.json['data'] == [
         {'id': 'F', 'text': 'Féminin'},
         {'id': 'M', 'text': 'Masculin'},
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_situation_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_SITUATIONS
+def test_read_situation_list(con, ref, app):
     url = get_endpoint('read-situation-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
-    assert resp.json['data'] == [
-        {'id': 'C', 'text': 'Célibataire'},
-        {'id': 'D', 'text': 'Divorcé (e)'},
-        {'id': 'CS', 'text': 'EN COURS DE SEPARATION'},
-        {'id': 'M', 'text': 'Marié (e)'},
-        {'id': 'P', 'text': 'Pacsé (e)'},
-        {'id': 'S', 'text': 'Séparé (e)'},
-        {'id': 'UL', 'text': 'UNION LIBRE'},
-        {'id': 'V', 'text': 'Veuf (ve)'},
-        {'id': 'VM', 'text': 'Vivant maritalement'},
+    assert resp.json['data'][:5] == [
+        {'id': 'C', 'code': 'C', 'text': 'Célibataire', 'libelle': 'Célibataire'},
+        {'id': 'D', 'code': 'D', 'text': 'Divorcé (e)', 'libelle': 'Divorcé (e)'},
+        {'id': 'CS', 'code': 'CS', 'text': 'EN COURS DE SEPARATION', 'libelle': 'EN COURS DE SEPARATION'},
+        {'id': 'M', 'code': 'M', 'text': 'Marié (e)', 'libelle': 'Marié (e)'},
+        {'id': 'P', 'code': 'P', 'text': 'Pacsé (e)', 'libelle': 'Pacsé (e)'},
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_street_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_STREET
+def test_read_street_list(con, ref, app):
     url = get_endpoint('read-street-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert len(resp.json['data']) == 3
     assert resp.json['data'] == [
-        {'id': 'AP0594', 'text': 'AVENUE PAULIANI'},
-        {'id': 'AS0264', 'text': 'RUE SAINT FRANCOIS DE PAULE'},
-        {'id': 'AM0330', 'text': 'TRAVERSE DES MARAICHERS'},
+        {'id': 'AP0594', 'text': 'AVENUE PAULIANI', 'idStreet': 'AP0594', 'libelleStreet': 'AVENUE PAULIANI'},
+        {
+            'id': 'AS0264',
+            'text': 'RUE SAINT FRANCOIS DE PAULE',
+            'idStreet': 'AS0264',
+            'libelleStreet': 'RUE SAINT FRANCOIS DE PAULE',
+        },
+        {
+            'id': 'AM0330',
+            'text': 'TRAVERSE DES MARAICHERS',
+            'idStreet': 'AM0330',
+            'libelleStreet': 'TRAVERSE DES MARAICHERS',
+        },
     ]
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_read_vaccin_list(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.return_value = READ_VACCIN
+def test_read_vaccin_list(con, ref, app):
     url = get_endpoint('read-vaccin-list')
-
     resp = app.get(url)
     assert resp.json['err'] == 0
     assert len(resp.json['data']) == 20
     assert resp.json['data'][:5] == [
-        {'id': 'BCG', 'text': 'BCG'},
-        {'id': 'CIB', 'text': 'CONTRE-INDICATION  TEMPORAIRE AU BCG'},
-        {'id': 'MONO', 'text': 'CONTROLE DU BCG (+)'},
-        {'id': 'MONON', 'text': 'CONTROLE DU BCG (-)'},
-        {'id': 'DTC', 'text': 'DIPHTERIE TETANOS COQUELUCHE'},
+        {'id': 'BCG', 'code': 'BCG', 'text': 'BCG', 'libelle': 'BCG'},
+        {
+            'id': 'CIB',
+            'code': 'CIB',
+            'text': 'CONTRE-INDICATION  TEMPORAIRE AU BCG',
+            'libelle': 'CONTRE-INDICATION  TEMPORAIRE AU BCG',
+        },
+        {'id': 'MONO', 'code': 'MONO', 'text': 'CONTROLE DU BCG (+)', 'libelle': 'CONTROLE DU BCG (+)'},
+        {'id': 'MONON', 'code': 'MONON', 'text': 'CONTROLE DU BCG (-)', 'libelle': 'CONTROLE DU BCG (-)'},
+        {
+            'id': 'DTC',
+            'code': 'DTC',
+            'text': 'DIPHTERIE TETANOS COQUELUCHE',
+            'libelle': 'DIPHTERIE TETANOS COQUELUCHE',
+        },
     ]
 
 
 @pytest.mark.parametrize("read_family", [READ_FAMILY, READ_FAMILY_LAX, READ_FAMILY_ORD])
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_read_family(mocked_post, mocked_get, read_family, con, app):
+def test_read_family(mocked_post, mocked_get, read_family, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        read_family,
-        READ_CATEGORIES,
-        READ_SITUATIONS,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-        READ_CSP,
-        READ_ORGAN,
-        READ_DIETCODE,
-        READ_PAI,
-    ]
+    mocked_post.return_value = read_family
     url = get_endpoint('read-family')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local')
     assert resp.json['err'] == 0
     data = resp.json['data']
     del data['RL1']
     del data['RL2']
@@ -827,43 +780,32 @@ def test_read_family_not_linked_error(con, app):
 
     resp = app.get(url + '?NameID=')
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_read_rl1(mocked_post, mocked_get, con, app):
+def test_read_rl1(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_FAMILY,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-        READ_CSP,
-    ]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('read-rl')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local&rl_id=613878')
     assert resp.json['err'] == 0
     assert resp.json['data']['firstname'] == 'JHON'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_read_rl2(mocked_post, mocked_get, con, app):
+def test_read_rl2(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_FAMILY,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-        READ_CSP,
-        READ_ORGAN,
-    ]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('read-rl')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local&rl_id=613879')
     assert resp.json['err'] == 0
     assert resp.json['data'] == {
         'num': '613879',
         'lastname': 'DOE',
@@ -920,36 +862,32 @@ def test_read_rl_not_linked_error(con, app):
 
     resp = app.get(url + '?NameID=local&rl_id=613879')
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_read_rl_not_found(mocked_post, mocked_get, con, app):
+def test_read_rl_not_found(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_FAMILY]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('read-rl')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local&rl_id=000000')
     assert resp.json['err'] == 'not-found'
     assert resp.json['err_desc'] == "no '000000' RL on '1312' family"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_read_person(mocked_post, mocked_get, con, app):
+def test_read_person(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_FAMILY,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-    ]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('read-person')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local&person_id=614059')
     assert resp.json['err'] == 0
     assert resp.json['data']['firstname'] == 'KENY'
 
 
@@ -958,38 +896,32 @@ def test_read_person_not_linked_error(con, app):
 
     resp = app.get(url + '?NameID=local&person_id=614059')
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_read_person_not_found(mocked_post, mocked_get, con, app):
+def test_read_person_not_found(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_FAMILY]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('read-person')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local&person_id=000000')
     assert resp.json['err'] == 'not-found'
     assert resp.json['err_desc'] == "no '000000' emergency person on '1312' family"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_read_child(mocked_post, mocked_get, con, app):
+def test_read_child(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_FAMILY,
-        READ_DIETCODE,
-        READ_PAI,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-    ]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('read-child')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local&child_id=613880')
     assert resp.json['err'] == 0
     assert resp.json['data']['firstname'] == 'JANNIS'
 
 
@@ -998,40 +930,32 @@ def test_read_child_not_linked_error(con, app):
 
     resp = app.get(url + '?NameID=local&child_id=613880')
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_read_child_not_found(mocked_post, mocked_get, con, app):
+def test_read_child_not_found(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_FAMILY,
-        READ_DIETCODE,
-        READ_PAI,
-    ]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('read-child')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local&child_id=000000')
     assert resp.json['err'] == 'not-found'
     assert resp.json['err_desc'] == "no '000000' child on '1312' family"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_read_child_person(mocked_post, mocked_get, con, app):
+def test_read_child_person(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_FAMILY,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-    ]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('read-child-person')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local&child_id=613880&person_id=614719')
     assert resp.json['err'] == 0
     assert resp.json['data']['personInfo']['firstname'] == 'AMEL'
 
 
@@ -1040,38 +964,32 @@ def test_read_child_person_not_linked_error(con, app):
 
     resp = app.get(url + '?NameID=local&child_id=613880&person_id=614719')
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_read_child_person_no_child_error(mocked_post, mocked_get, con, app):
+def test_read_child_person_no_child_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_FAMILY,
-    ]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('read-child-person')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local&child_id=42&person_id=614719')
     assert resp.json['err'] == 'not-found'
     assert resp.json['err_desc'] == "no '42' child on '1312' family"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_read_child_person_no_person_error(mocked_post, mocked_get, con, app):
+def test_read_child_person_no_person_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_FAMILY,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-    ]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('read-child-person')
     Link.objects.create(resource=con, family_id='1312', name_id='local')
 
     resp = app.get(url + '?NameID=local&child_id=613880&person_id=000000')
     assert resp.json['err'] == 'not-found'
     assert resp.json['err_desc'] == "no '000000' authorized person on '613880' child"
 
 
@@ -1133,29 +1051,19 @@ def test_is_child_exists(mocked_post, mocked_get, post_response, result, con, ap
     }
     resp = app.post_json(url, params=params)
     assert resp.json['err'] == 0
     assert resp.json['data'] == result
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_family(mocked_post, mocked_get, con, app):
+def test_create_family(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_CATEGORIES,
-        READ_SITUATIONS,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-        READ_CSP,
-        READ_ORGAN,
-        READ_DIETCODE,
-        READ_VACCIN,
-        CREATE_FAMILY,
-    ]
+    mocked_post.return_value = CREATE_FAMILY
     url = get_endpoint('create-family')
     params = {
         'category': 'ACCEUI',
         'situation': 'C',
         'rl1/civility': 'M.',
         'rl1/firstname': 'Jhon',
         'rl1/lastname': 'Doe',
         'rl1/quality': 'AU',
@@ -1231,25 +1139,19 @@ def test_create_family_already_linked_error(con, app):
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'already-linked'
     assert resp.json['err_desc'] == 'User already linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_family_maelis_error(mocked_post, mocked_get, con, app):
+def test_create_family_maelis_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_CATEGORIES,
-        READ_SITUATIONS,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-        CREATE_FAMILY_ERR,
-    ]
+    mocked_post.return_value = CREATE_FAMILY_ERR
     url = get_endpoint('create-family')
     params = {
         'category': 'ACCEUI',
         'situation': 'C',
         'rl1/civility': 'M.',
         'rl1/firstname': 'Jhon',
         'rl1/lastname': 'Doe',
         'rl1/quality': 'AU',
@@ -1259,30 +1161,17 @@ def test_create_family_maelis_error(mocked_post, mocked_get, con, app):
         'rl1/adresse/zipcode': '75014',
     }
 
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'E54a, E54a'
     assert 'Il existe déjà' in resp.json['err_desc']
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_create_family_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_CATEGORIES,
-        READ_SITUATIONS,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-        READ_CSP,
-        READ_ORGAN,
-        READ_DIETCODE,
-        READ_VACCIN,
-    ]
+def test_create_family_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('create-family')
     params = {
         'category': 'ACCEUI',
         'situation': 'C',
         'rl1/civility': 'M.',
         'rl1/firstname': 'Jhon',
         'rl1/lastname': 'Doe',
         'rl1/quality': 'AU',
@@ -1313,30 +1202,19 @@ def test_create_family_wrong_referential_key_error(mocked_post, mocked_get, con,
     assert (
         resp.json['err_desc']
         == "childList/0/medicalRecord/vaccinList/0/code key value 'plop' do not belong to 'Vaccin' referential"
     )
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_family(mocked_post, mocked_get, con, app):
+def test_update_family(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_CATEGORIES,
-        READ_SITUATIONS,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-        READ_CSP,
-        READ_ORGAN,
-        READ_DIETCODE,
-        READ_PAI,
-        READ_VACCIN,
-        UPDATE_FAMILY,
-    ]
+    mocked_post.return_value = UPDATE_FAMILY
     url = get_endpoint('update-family')
     params = {
         'category': 'BI',
         'situation': 'C',
         'rl1/civility': 'M.',
         'rl1/firstname': 'Jhon',
         'rl1/lastname': 'Doe',
         'rl1/quality': 'AU',
@@ -1397,23 +1275,19 @@ def test_update_family_not_linked_error(con, app):
 
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_family_maelis_error(mocked_post, mocked_get, con, app):
+def test_update_family_maelis_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_CATEGORIES,
-        READ_SITUATIONS,
-        UPDATE_FAMILY_ERR,
-    ]
+    mocked_post.return_value = UPDATE_FAMILY_ERR
     url = get_endpoint('update-family')
     params = {
         'category': 'ACCEUI',
         'situation': 'C',
         'childList/0/lastname': 'Zimmerman',
         'childList/0/firstname': 'Robert',
         'childList/0/sexe': 'M',
         'childList/0/birth/dateBirth': '1941-05-24',
@@ -1423,17 +1297,17 @@ def test_update_family_maelis_error(mocked_post, mocked_get, con, app):
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'E65a'
     assert "E65a : Il existe déjà un enfant" in resp.json['err_desc']
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_family_soap_error(mocked_post, mocked_get, con, app):
+def test_update_family_soap_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.return_value = UPDATE_FAMILY_500
     url = get_endpoint('update-family')
     params = {
         'nbChild': '100',
         'category': 'BI',
         'situation': 'C',
         'rl1/civility': 'M.',
@@ -1443,35 +1317,21 @@ def test_update_family_soap_error(mocked_post, mocked_get, con, app):
         'rl1/birth/dateBirth': '1938-07-26',
         'rl1/adresse/street1': 'Chateau',
         'rl1/adresse/town': 'Paris',
         'rl1/adresse/zipcode': '75014',
     }
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
-    assert resp.json['err'] == 'Family-readCategoryList-soap:Server'
+    assert resp.json['err'] == 'Family-updateFamily-soap:Server'
     assert 'Une erreur est survenue' in resp.json['err_desc']
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_update_family_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_CATEGORIES,
-        READ_SITUATIONS,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-        READ_CSP,
-        READ_ORGAN,
-        READ_DIETCODE,
-        READ_PAI,
-        READ_VACCIN,
-    ]
+def test_update_family_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('update-family')
     params = {
         'category': 'BI',
         'situation': 'C',
         'rl1/civility': 'M.',
         'rl1/firstname': 'Jhon',
         'rl1/lastname': 'Doe',
         'rl1/quality': 'AU',
@@ -1508,25 +1368,19 @@ def test_update_family_wrong_referential_key_error(mocked_post, mocked_get, con,
     assert (
         resp.json['err_desc']
         == "childList/0/medicalRecord/vaccinList/0/code key value 'plop' do not belong to 'Vaccin' referential"
     )
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_rl1(mocked_post, mocked_get, con, app):
+def test_create_rl1(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_CATEGORIES,
-        READ_SITUATIONS,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-        CREATE_FAMILY,
-    ]
+    mocked_post.return_value = CREATE_FAMILY
     url = get_endpoint('create-rl1')
     params = {
         'category': 'ACCEUI',
         'situation': 'C',
         'rl1/civility': 'M.',
         'rl1/firstname': 'Jhon',
         'rl1/lastname': 'Doe',
         'rl1/quality': 'AU',
@@ -1579,21 +1433,17 @@ def test_create_rl1_already_linked_error(con, app):
     }
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'already-linked'
     assert resp.json['err_desc'] == 'User already linked to family'
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_create_rl1_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CATEGORIES, READ_SITUATIONS, READ_CIVILITIES, READ_QUALITIES]
+def test_create_rl1_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('create-rl1')
     params = {
         'category': 'ACCEUI',
         'situation': 'C',
         'rl1/civility': 'M.',
         'rl1/firstname': 'Jhon',
         'rl1/lastname': 'Doe',
         'rl1/quality': 'AU',
@@ -1609,25 +1459,19 @@ def test_create_rl1_wrong_referential_key_error(mocked_post, mocked_get, con, ap
     assert (
         resp.json['err_desc']
         == "rl1/adresse/numComp key value 'plop' do not belong to 'Complement' referential"
     )
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_rl1_maelis_error(mocked_post, mocked_get, con, app):
+def test_create_rl1_maelis_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [
-        READ_CATEGORIES,
-        READ_SITUATIONS,
-        READ_CIVILITIES,
-        READ_QUALITIES,
-        CREATE_FAMILY_ERR,
-    ]
+    mocked_post.return_value = CREATE_FAMILY_ERR
     url = get_endpoint('create-rl1')
     params = {
         'category': 'ACCEUI',
         'situation': 'C',
         'rl1/civility': 'M.',
         'rl1/firstname': 'Jhon',
         'rl1/lastname': 'Doe',
         'rl1/quality': 'AU',
@@ -1639,19 +1483,19 @@ def test_create_rl1_maelis_error(mocked_post, mocked_get, con, app):
 
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'already-rl1'
     assert 'Il existe déjà' in resp.json['err_desc']
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_rl1(mocked_post, mocked_get, con, app):
+def test_update_rl1(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES, READ_RL1_FAMILY, UPDATE_FAMILY]
+    mocked_post.side_effect = [READ_RL1_FAMILY, UPDATE_FAMILY]
     url = get_endpoint('update-rl1')
     params = {
         'civility': 'M.',
         'firstname': 'Jhonny',
         'lastname': 'Doe',
         'quality': 'PERE',
         'birth/dateBirth': '1943-06-15',
     }
@@ -1674,17 +1518,17 @@ def test_update_rl1_not_linked_error(con, app):
 
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_rl1_connection_error(mocked_post, mocked_get, con, app):
+def test_update_rl1_connection_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.side_effect = CONNECTION_ERROR
     url = get_endpoint('update-rl1')
     params = {
         'civility': 'M.',
         'firstname': 'Jhonny',
         'lastname': 'Doe',
         'quality': 'PERE',
@@ -1692,21 +1536,17 @@ def test_update_rl1_connection_error(mocked_post, mocked_get, con, app):
     }
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params, status=500)
     assert resp.json['err']
     assert resp.json['err_desc'] == 'No address associated with hostname'
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_update_rl1_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES]
+def test_update_rl1_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('update-rl1')
     params = {
         'civility': 'M.',
         'firstname': 'Jhonny',
         'lastname': 'Doe',
         'quality': 'plop',
         'birth/dateBirth': '1943-06-15',
     }
@@ -1714,19 +1554,19 @@ def test_update_rl1_wrong_referential_key_error(mocked_post, mocked_get, con, ap
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'wrong-key'
     assert resp.json['err_desc'] == "quality key value 'plop' do not belong to 'Quality' required referential"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_rl2(mocked_post, mocked_get, con, app):
+def test_create_rl2(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES, READ_RL1_FAMILY, UPDATE_FAMILY]
+    mocked_post.side_effect = [READ_RL1_FAMILY, UPDATE_FAMILY]
     url = get_endpoint('create-rl2')
     params = {
         'civility': 'MME',
         'firstname': 'JANE',
         'lastname': 'DOE',
         'maidenName': 'Smith',
         'quality': 'MERE',
         'birth/dateBirth': '1940-06-22',
@@ -1760,17 +1600,17 @@ def test_create_rl2_not_linked_error(con, app):
 
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_rl2_connection_error(mocked_post, mocked_get, con, app):
+def test_create_rl2_connection_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.side_effect = CONNECTION_ERROR
     url = get_endpoint('create-rl2')
     params = {
         'civility': 'MME',
         'firstname': 'JANE',
         'lastname': 'DOE',
         'maidenName': 'Smith',
@@ -1785,19 +1625,19 @@ def test_create_rl2_connection_error(mocked_post, mocked_get, con, app):
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params, status=500)
     assert resp.json['err']
     assert resp.json['err_desc'] == 'No address associated with hostname'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_rl2_already_exists_error(mocked_post, mocked_get, con, app):
+def test_create_rl2_already_exists_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES, READ_FAMILY, READ_FAMILY]
+    mocked_post.side_effect = [READ_FAMILY, READ_FAMILY]
     url = get_endpoint('create-rl2')
     params = {
         'civility': 'MME',
         'firstname': 'JANE',
         'lastname': 'DOE',
         'maidenName': 'Smith',
         'quality': 'MERE',
         'birth/dateBirth': '1940-06-22',
@@ -1808,21 +1648,17 @@ def test_create_rl2_already_exists_error(mocked_post, mocked_get, con, app):
     }
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'already-rl2'
     assert resp.json['err_desc'] == 'RL2 already defined on family'
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_create_rl2_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES, READ_RL1_FAMILY]
+def test_create_rl2_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('create-rl2')
     params = {
         'civility': 'MME',
         'firstname': 'JANE',
         'lastname': 'DOE',
         'maidenName': 'Smith',
         'quality': 'plop',
         'birth/dateBirth': '1940-06-22',
@@ -1835,19 +1671,19 @@ def test_create_rl2_wrong_referential_key_error(mocked_post, mocked_get, con, ap
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'wrong-key'
     assert resp.json['err_desc'] == "quality key value 'plop' do not belong to 'Quality' required referential"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_rl2(mocked_post, mocked_get, con, app):
+def test_update_rl2(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES, READ_FAMILY, UPDATE_FAMILY]
+    mocked_post.side_effect = [READ_FAMILY, UPDATE_FAMILY]
     url = get_endpoint('update-rl2')
     params = {
         'civility': 'MME',
         'firstname': 'JANE',
         'lastname': 'DOE',
         'maidenName': 'Smith',
         'quality': 'MERE',
         'birth/dateBirth': '1940-06-22',
@@ -1872,17 +1708,17 @@ def test_update_rl2_not_linked_error(con, app):
 
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_rl2_connection_error(mocked_post, mocked_get, con, app):
+def test_update_rl2_connection_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.side_effect = CONNECTION_ERROR
     url = get_endpoint('update-rl2')
     params = {
         'civility': 'MME',
         'firstname': 'JANE',
         'lastname': 'DOE',
         'maidenName': 'Smith',
@@ -1893,40 +1729,36 @@ def test_update_rl2_connection_error(mocked_post, mocked_get, con, app):
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params, status=500)
     assert resp.json['err']
     assert resp.json['err_desc'] == 'No address associated with hostname'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_rl2_not_exists_error(mocked_post, mocked_get, con, app):
+def test_update_rl2_not_exists_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES, READ_RL1_FAMILY]
+    mocked_post.return_value = READ_RL1_FAMILY
     url = get_endpoint('update-rl2')
     params = {
         'civility': 'MME',
         'firstname': 'JANE',
         'lastname': 'DOE',
         'maidenName': 'Smith',
         'quality': 'MERE',
         'birth/dateBirth': '1940-06-22',
     }
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'no-rl2'
     assert resp.json['err_desc'] == 'No RL2 to update on family'
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_update_rl2_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES]
+def test_update_rl2_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('update-rl2')
     params = {
         'civility': 'MME',
         'firstname': 'JANE',
         'lastname': 'DOE',
         'maidenName': 'Smith',
         'quality': 'plop',
         'birth/dateBirth': '1940-06-22',
@@ -1935,17 +1767,17 @@ def test_update_rl2_wrong_referential_key_error(mocked_post, mocked_get, con, ap
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'wrong-key'
     assert resp.json['err_desc'] == "quality key value 'plop' do not belong to 'Quality' required referential"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_child(mocked_post, mocked_get, con, app):
+def test_create_child(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.return_value = CREATE_CHILD
     url = get_endpoint('create-child')
     params = {
         'lastname': 'DOE',
         'firstname': 'JANNIS',
         'sexe': 'F',
         'birth/dateBirth': '1943-01-19',
@@ -1984,21 +1816,17 @@ def test_create_child_not_linked_error(con, app):
         'birth/place': 'Port Arthur',
     }
 
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_create_child_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = []
+def test_create_child_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('create-child')
     params = {
         'lastname': 'DOE',
         'firstname': 'JANNIS',
         'sexe': 'plop',
         'birth/dateBirth': '1943-01-19',
         'birth/place': 'Port Arthur',
     }
@@ -2006,17 +1834,17 @@ def test_create_child_wrong_referential_key_error(mocked_post, mocked_get, con,
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'wrong-key'
     assert resp.json['err_desc'] == "sexe key value 'plop' do not belong to 'Sex' required referential"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_child_connection_error(mocked_post, mocked_get, con, app):
+def test_create_child_connection_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.side_effect = CONNECTION_ERROR
     url = get_endpoint('create-child')
     params = {
         'lastname': 'DOE',
         'firstname': 'JANNIS',
         'sexe': 'F',
         'birth/dateBirth': '1943-01-19',
@@ -2026,17 +1854,17 @@ def test_create_child_connection_error(mocked_post, mocked_get, con, app):
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params, status=500)
     assert resp.json['err']
     assert resp.json['err_desc'] == 'No address associated with hostname'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_child_maelis_error(mocked_post, mocked_get, con, app):
+def test_create_child_maelis_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.return_value = CREATE_CHILD_ERR
     url = get_endpoint('create-child')
     params = {
         'lastname': 'DOE',
         'firstname': 'JANNIS',
         'sexe': 'F',
         'birth/dateBirth': '1943-01-19',
@@ -2046,17 +1874,17 @@ def test_create_child_maelis_error(mocked_post, mocked_get, con, app):
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'already-child'
     assert 'Il existe déjà' in resp.json['err_desc']
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_child(mocked_post, mocked_get, con, app):
+def test_update_child(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.side_effect = [READ_FAMILY, UPDATE_FAMILY]
     url = get_endpoint('update-child')
     params = {
         'lastname': 'DOE',
         'firstname': 'JANNIS',
         'sexe': 'F',
         'birth/dateBirth': '1943-01-19',
@@ -2081,21 +1909,17 @@ def test_update_child_not_linked_error(con, app):
         'birth/place': 'Port Arthur',
     }
 
     resp = app.post_json(url + '?NameID=local&child_id=613880', params=params)
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_update_child_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = []
+def test_update_child_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('create-child')
     params = {
         'lastname': 'DOE',
         'firstname': 'JANNIS',
         'sexe': 'plop',
         'birth/dateBirth': '1943-01-19',
         'birth/place': 'Port Arthur',
     }
@@ -2103,17 +1927,17 @@ def test_update_child_wrong_referential_key_error(mocked_post, mocked_get, con,
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'wrong-key'
     assert resp.json['err_desc'] == "sexe key value 'plop' do not belong to 'Sex' required referential"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_child_connection_error(mocked_post, mocked_get, con, app):
+def test_update_child_connection_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.side_effect = CONNECTION_ERROR
     url = get_endpoint('update-child')
     params = {
         'lastname': 'DOE',
         'firstname': 'JANNIS',
         'sexe': 'F',
         'birth/dateBirth': '1943-01-19',
@@ -2123,17 +1947,17 @@ def test_update_child_connection_error(mocked_post, mocked_get, con, app):
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&child_id=613880', params=params, status=500)
     assert resp.json['err']
     assert resp.json['err_desc'] == 'No address associated with hostname'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_child_not_exists_error(mocked_post, mocked_get, con, app):
+def test_update_child_not_exists_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.return_value = READ_RL1_FAMILY
     url = get_endpoint('update-child')
     params = {
         'lastname': 'DOE',
         'firstname': 'JANNIS',
         'sexe': 'F',
         'birth/dateBirth': '1943-01-19',
@@ -2143,19 +1967,19 @@ def test_update_child_not_exists_error(mocked_post, mocked_get, con, app):
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&child_id=42', params=params)
     assert resp.json['err'] == 'no-child'
     assert resp.json['err_desc'] == 'No child 42 to update on family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_coordinate(mocked_post, mocked_get, con, app):
+def test_update_coordinate(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CSP, READ_ORGAN, UPDATE_FAMILY]
+    mocked_post.return_value = UPDATE_FAMILY
     url = get_endpoint('update-coordinate')
     params = {
         'adresse/num': '169',
         'adresse/numComp': 'B',
         'adresse/street1': 'Château',
         'adresse/street2': None,
         'adresse/town': 'Paris',
         'adresse/zipcode': '75014',
@@ -2193,17 +2017,17 @@ def test_update_coordinate_schema_error(con, app):
     }
     resp = app.post_json(url + '?NameID=local&rl_id=613878', params=params, status=400)
     assert resp.json['err'] == 1
     assert resp.json['err_desc'] == "'true more text' is not of type 'boolean'"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_coordinate_wrong_referential_key_error(mocked_post, mocked_get, con, app):
+def test_update_coordinate_wrong_referential_key_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
     mocked_post.return_value = UPDATE_FAMILY
     url = get_endpoint('update-coordinate')
     params = {
         'adresse/num': '169',
         'adresse/numComp': 'plop',
         'adresse/street1': 'Château',
         'adresse/street2': None,
@@ -2216,19 +2040,19 @@ def test_update_coordinate_wrong_referential_key_error(mocked_post, mocked_get,
     assert resp.json['err'] == 'wrong-key'
     assert (
         resp.json['err_desc'] == "adresse/numComp key value 'plop' do not belong to 'Complement' referential"
     )
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_person(mocked_post, mocked_get, con, app):
+def test_create_person(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_QUALITIES, READ_FAMILY, UPDATE_FAMILY]
+    mocked_post.side_effect = [READ_FAMILY, UPDATE_FAMILY]
     url = get_endpoint('create-person')
     params = {
         'civility': None,
         'firstname': 'Mathias',
         'lastname': 'Cassel',
         'quality': 'O',
         'sexe': 'M',
         'dateBirth': '1972-01-01',
@@ -2294,21 +2118,17 @@ def test_create_person_not_linked_error(con, app):
         'contact/mail': None,
     }
 
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_create_person_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_QUALITIES]
+def test_create_person_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('create-person')
     params = {
         'civility': None,
         'firstname': 'Mathias',
         'lastname': 'Cassel',
         'quality': 'O',
         'sexe': 'plop',
         'dateBirth': '1972-01-01',
@@ -2320,19 +2140,19 @@ def test_create_person_wrong_referential_key_error(mocked_post, mocked_get, con,
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local', params=params)
     assert resp.json['err'] == 'wrong-key'
     assert resp.json['err_desc'] == "sexe key value 'plop' do not belong to 'Sex' referential"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_person(mocked_post, mocked_get, con, app):
+def test_update_person(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_QUALITIES, READ_FAMILY, UPDATE_FAMILY]
+    mocked_post.side_effect = [READ_FAMILY, UPDATE_FAMILY]
     url = get_endpoint('update-person')
     params = {
         'civility': None,
         'firstname': 'Mathias',
         'lastname': 'Cassel',
         'quality': 'O',
         'sexe': 'M',
         'dateBirth': '1972-01-01',
@@ -2363,19 +2183,19 @@ def test_update_person_not_linked_error(con, app):
 
     resp = app.post_json(url + '?NameID=local&person_id=614059', params=params)
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_person_not_found(mocked_post, mocked_get, con, app):
+def test_update_person_not_found(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_QUALITIES, READ_FAMILY]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('update-person')
     params = {
         'civility': None,
         'firstname': 'Mathias',
         'lastname': 'Cassel',
         'quality': 'O',
         'sexe': 'M',
         'dateBirth': '1972-01-01',
@@ -2409,30 +2229,30 @@ def test_delete_person_not_linked_error(con, app):
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
 def test_delete_person_not_found(mocked_post, mocked_get, con, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_FAMILY]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('delete-person')
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&person_id=000000')
     assert resp.json['err'] == 'not-found'
     assert resp.json['err_desc'] == "no '000000' authorized person on '1312' family"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_child_person(mocked_post, mocked_get, con, app):
+def test_create_child_person(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES, READ_FAMILY, UPDATE_CHILD_AUTO]
+    mocked_post.side_effect = [READ_FAMILY, UPDATE_CHILD_AUTO]
     url = get_endpoint('create-child-person')
     params = {
         'personInfo/civility': 'MME',
         'personInfo/firstname': 'Diana',
         'personInfo/lastname': 'Ross',
         'personInfo/sexe': 'F',
         'personInfo/dateBirth': '1944-03-26',
         'personInfo/contact/phone': '0199999999',
@@ -2480,21 +2300,17 @@ def test_create_child_person_not_linked_error(con, app):
         'personQuality/code': 'TUTEUR',
     }
 
     resp = app.post_json(url + '?NameID=local&child_id=613880', params=params)
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_create_child_person_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES]
+def test_create_child_person_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('create-child-person')
     params = {
         'personInfo/civility': 'MME',
         'personInfo/firstname': 'Diana',
         'personInfo/lastname': 'Ross',
         'personInfo/sexe': 'plop',
         'personInfo/dateBirth': '1944-03-26',
         'personInfo/contact/phone': '0199999999',
@@ -2506,19 +2322,19 @@ def test_create_child_person_wrong_referential_key_error(mocked_post, mocked_get
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&child_id=613880', params=params)
     assert resp.json['err'] == 'wrong-key'
     assert resp.json['err_desc'] == "personInfo/sexe key value 'plop' do not belong to 'Sex' referential"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_create_child_person_no_child_error(mocked_post, mocked_get, con, app):
+def test_create_child_person_no_child_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES, READ_FAMILY]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('create-child-person')
     params = {
         'personInfo/civility': 'MME',
         'personInfo/firstname': 'Diana',
         'personInfo/lastname': 'Ross',
         'personInfo/sexe': 'F',
         'personInfo/dateBirth': '1944-03-26',
         'personInfo/contact/phone': '01999999999',
@@ -2530,19 +2346,19 @@ def test_create_child_person_no_child_error(mocked_post, mocked_get, con, app):
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&child_id=42', params=params)
     assert resp.json['err'] == 'not-found'
     assert resp.json['err_desc'] == "no '42' child on '1312' family"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_child_person(mocked_post, mocked_get, con, app):
+def test_update_child_person(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES, READ_FAMILY, UPDATE_FAMILY]
+    mocked_post.side_effect = [READ_FAMILY, UPDATE_FAMILY]
     url = get_endpoint('update-child-person')
     params = {
         'personInfo/civility': 'M.',
         'personInfo/firstname': 'Angelo',
         'personInfo/lastname': 'Bent',
         'personInfo/sexe': 'M',
         'personInfo/dateBirth': '1985-06-22',
         'personInfo/contact/phone': '0102030405',
@@ -2570,21 +2386,17 @@ def test_update_child_person_not_linked_error(con, app):
         'personQuality/code': 'O',
     }
 
     resp = app.post_json(url + '?NameID=local&child_id=613880&person_id=614719', params=params)
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_update_child_person_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES]
+def test_update_child_person_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('update-child-person')
     params = {
         'personInfo/civility': 'M.',
         'personInfo/firstname': 'Angelo',
         'personInfo/lastname': 'Bent',
         'personInfo/sexe': 'plop',
         'personInfo/dateBirth': '1985-06-22',
         'personInfo/contact/phone': '0102030405',
@@ -2596,19 +2408,19 @@ def test_update_child_person_wrong_referential_key_error(mocked_post, mocked_get
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&child_id=613880&person_id=614719', params=params)
     assert resp.json['err'] == 'wrong-key'
     assert resp.json['err_desc'] == "personInfo/sexe key value 'plop' do not belong to 'Sex' referential"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_child_person_no_child_error(mocked_post, mocked_get, con, app):
+def test_update_child_person_no_child_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES, READ_FAMILY]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('update-child-person')
     params = {
         'personInfo/civility': 'M.',
         'personInfo/firstname': 'Angelo',
         'personInfo/lastname': 'Bent',
         'personInfo/dateBirth': '1985-06-22',
         'personInfo/contact/phone': '0102030405',
         'personInfo/contact/mobile': None,
@@ -2619,19 +2431,19 @@ def test_update_child_person_no_child_error(mocked_post, mocked_get, con, app):
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&child_id=42&person_id=614719', params=params)
     assert resp.json['err'] == 'not-found'
     assert resp.json['err_desc'] == "no '42' child on '1312' family"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_child_person_not_found(mocked_post, mocked_get, con, app):
+def test_update_child_person_not_found(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_CIVILITIES, READ_QUALITIES, READ_FAMILY]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('update-child-person')
     params = {
         'personInfo/civility': 'M.',
         'personInfo/firstname': 'Angelo',
         'personInfo/lastname': 'Bent',
         'personInfo/dateBirth': '1985-06-22',
         'personInfo/contact/phone': '0102030405',
         'personInfo/contact/mobile': None,
@@ -2665,43 +2477,43 @@ def test_delete_child_person_not_linked_error(con, app):
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
 def test_delete_child_person_no_child_error(mocked_post, mocked_get, con, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_FAMILY]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('delete-child-person')
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&child_id=42&person_id=614719')
     assert resp.json['err'] == 'not-found'
     assert resp.json['err_desc'] == "no '42' child on '1312' family"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
 def test_delete_child_person_no_person_error(mocked_post, mocked_get, con, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_FAMILY]
+    mocked_post.return_value = READ_FAMILY
     url = get_endpoint('delete-child-person')
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&child_id=613880&person_id=000000')
     assert resp.json['err'] == 'not-found'
     assert resp.json['err_desc'] == "No '000000' authorized person on '613880' child"
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_child_dietcode(mocked_post, mocked_get, con, app):
+def test_update_child_dietcode(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_DIETCODE, UPDATE_DIETCODE]
+    mocked_post.return_value = UPDATE_DIETCODE
     url = get_endpoint('update-child-dietcode')
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&child_id=613878&dietcode=RSV')
     assert_sent_payload(mocked_post, 'Q_update_child_dietcode.xml')
     assert resp.json['err'] == 0
     assert resp.json['data'] == 'ok'
 
@@ -2709,36 +2521,32 @@ def test_update_child_dietcode(mocked_post, mocked_get, con, app):
 def test_update_child_dietcode_not_linked_error(con, app):
     url = get_endpoint('update-child-dietcode')
 
     resp = app.post_json(url + '?NameID=local&child_id=613878&dietcode=RVS')
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_update_child_dietcode_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_DIETCODE, UPDATE_DIETCODE]
+def test_update_child_dietcode_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('update-child-dietcode')
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&child_id=613878&dietcode=plop')
     assert resp.json['err'] == 'wrong-key'
     assert (
         resp.json['err_desc'] == "dietcode parameter key value 'plop' do not belong to 'DietCode' referential"
     )
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_child_pai(mocked_post, mocked_get, con, app):
+def test_update_child_pai(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_PAI, UPDATE_PAI]
+    mocked_post.return_value = UPDATE_PAI
     url = get_endpoint('update-child-pai')
     params = {
         'code': 'PAIALI',
         'dateDeb': '2022-01-01',
         'dateFin': '',
         'description': 'some text',
     }
 
@@ -2794,19 +2602,19 @@ def test_update_child_pai_not_linked_error(con, app):
 
     resp = app.post_json(url + '?NameID=local&child_id=613878', params=params)
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_child_pai_soap_error(mocked_post, mocked_get, con, app):
+def test_update_child_pai_soap_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_PAI, UPDATE_PAI_500]
+    mocked_post.return_value = UPDATE_PAI_500
     url = get_endpoint('update-child-pai')
     params = {
         'code': 'PAIALI',
         'dateDeb': '2022-01-01',
         'dateFin': '',
         'description': 'a' * 501,
     }
 
@@ -2815,19 +2623,19 @@ def test_update_child_pai_soap_error(mocked_post, mocked_get, con, app):
     assert resp.json['err'] == 'Family-updateChildPAI-soap:Server'
     assert 'Une erreur est survenue' in resp.json['err_desc']
     assert 'valeur trop grande' in resp.json['err_desc']
     assert 'maximum : 500' in resp.json['err_desc']
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_child_medical_record(mocked_post, mocked_get, con, app):
+def test_update_child_medical_record(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_VACCIN, UPDATE_MEDICAL]
+    mocked_post.return_value = UPDATE_MEDICAL
     url = get_endpoint('update-child-medical-record')
     params = {
         'familyDoctor/name': 'Dre',
         'familyDoctor/phone': '0612341234',
         'familyDoctor/address/street1': 'Alameda',
         'familyDoctor/address/zipcode': '90220',
         'familyDoctor/address/town': 'Compton',
         'allergy1': 'butterscotch, imitation butterscotch, glow-in-the-dark monster make-up, and shrimp',
@@ -2848,19 +2656,19 @@ def test_update_child_medical_record(mocked_post, mocked_get, con, app):
     resp = app.post_json(url + '?NameID=local&child_id=613878', params=params)
     assert_sent_payload(mocked_post, 'Q_update_child_medical_record.xml')
     assert resp.json['err'] == 0
     assert resp.json['data'] == 'ok'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_child_medical_record_with_empty_vaccin_list(mocked_post, mocked_get, con, app):
+def test_update_child_medical_record_with_empty_vaccin_list(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_VACCIN, UPDATE_MEDICAL]
+    mocked_post.return_value = UPDATE_MEDICAL
     url = get_endpoint('update-child-medical-record')
     params = {
         'familyDoctor/name': 'Dre',
         'familyDoctor/phone': '0612341234',
         'familyDoctor/address/street1': 'Alameda',
         'familyDoctor/address/zipcode': '90220',
         'familyDoctor/address/town': 'Compton',
         'allergy1': 'butterscotch, imitation butterscotch, glow-in-the-dark monster make-up, and shrimp',
@@ -2884,37 +2692,33 @@ def test_update_child_medical_record_not_linked_error(con, app):
 
     resp = app.post_json(url + '?NameID=local&child_id=613878', params={})
     assert resp.json['err'] == 'not-linked'
     assert resp.json['err_desc'] == 'User not linked to family'
 
 
 @mock.patch('passerelle.utils.Request.get')
 @mock.patch('passerelle.utils.Request.post')
-def test_update_child_medical_record_soap_error(mocked_post, mocked_get, con, app):
+def test_update_child_medical_record_soap_error(mocked_post, mocked_get, con, ref, app):
     mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_VACCIN, UPDATE_MEDICAL_500]
+    mocked_post.return_value = UPDATE_MEDICAL_500
     url = get_endpoint('update-child-medical-record')
     params = {
         'vaccinList/0/code': 'DTC',
         'vaccinList/0/vaccinationDate': '2022-02-31',
     }
 
     Link.objects.create(resource=con, family_id='1312', name_id='local')
     resp = app.post_json(url + '?NameID=local&child_id=613878', params=params)
     assert resp.json['err'] == 'Family-updateChildMedicalRecord-soap:Client'
     assert 'Unmarshalling Error' in resp.json['err_desc']
     assert 'pas une valeur de calendrier grégorien' in resp.json['err_desc']
 
 
-@mock.patch('passerelle.utils.Request.get')
-@mock.patch('passerelle.utils.Request.post')
-def test_update_child_medical_record_wrong_referential_key_error(mocked_post, mocked_get, con, app):
-    mocked_get.return_value = FAMILY_SERVICE_WSDL
-    mocked_post.side_effect = [READ_VACCIN]
+def test_update_child_medical_record_wrong_referential_key_error(con, ref, app):
     url = get_endpoint('update-child-medical-record')
     params = {
         'familyDoctor/name': 'Dre',
         'familyDoctor/phone': '0612341234',
         'familyDoctor/address/street1': 'Alameda',
         'familyDoctor/address/zipcode': '90220',
         'familyDoctor/address/town': 'Compton',
         'vaccinList/0/code': 'DTC',
-- 
2.30.2

