View Javadoc
1   /*
2    * Copyright (C) 2022 B3Partners B.V.
3    *
4    * SPDX-License-Identifier: MIT
5    *
6    */
7   package nl.b3p;
8   
9   import static org.junit.jupiter.api.Assertions.*;
10  import static org.junit.jupiter.api.Assumptions.assumeFalse;
11  import static org.junit.jupiter.api.Assumptions.assumeTrue;
12  import static org.junit.jupiter.params.provider.Arguments.arguments;
13  
14  import java.io.File;
15  import java.io.FileInputStream;
16  import java.util.HashSet;
17  import java.util.List;
18  import java.util.Objects;
19  import java.util.Set;
20  import java.util.concurrent.locks.Lock;
21  import java.util.concurrent.locks.ReentrantLock;
22  import java.util.stream.Collectors;
23  import java.util.stream.Stream;
24  import nl.b3p.brmo.loader.BrmoFramework;
25  import nl.b3p.brmo.loader.entity.Bericht;
26  import nl.b3p.brmo.loader.entity.LaadProces;
27  import nl.b3p.brmo.loader.util.BrmoException;
28  import nl.b3p.brmo.test.util.database.dbunit.CleanUtil;
29  import nl.b3p.jdbc.util.converter.OracleConnectionUnwrapper;
30  import org.apache.commons.dbcp2.BasicDataSource;
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.dbunit.database.DatabaseConfig;
34  import org.dbunit.database.DatabaseConnection;
35  import org.dbunit.database.DatabaseDataSourceConnection;
36  import org.dbunit.database.IDatabaseConnection;
37  import org.dbunit.dataset.IDataSet;
38  import org.dbunit.dataset.ITable;
39  import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
40  import org.dbunit.ext.oracle.Oracle10DataTypeFactory;
41  import org.dbunit.ext.postgresql.PostgresqlDataTypeFactory;
42  import org.dbunit.operation.DatabaseOperation;
43  import org.junit.jupiter.api.AfterEach;
44  import org.junit.jupiter.api.BeforeEach;
45  import org.junit.jupiter.api.DisplayName;
46  import org.junit.jupiter.api.Tag;
47  import org.junit.jupiter.params.ParameterizedTest;
48  import org.junit.jupiter.params.provider.Arguments;
49  import org.junit.jupiter.params.provider.MethodSource;
50  
51  /**
52   * Testcases voor 1 of meer objecten uit stand en per object 1 mutatie. Draaien met: {@code mvn
53   * -Dit.test=Brk2StandMutatieGedeeldeStukkenVerwerkingIntegrationTest -Dtest.onlyITs=true verify
54   * -Ppostgresql -pl brmo-loader > /tmp/postgresql.log} of {@code mvn
55   * -Dit.test=Brk2StandMutatieGedeeldeStukkenVerwerkingIntegrationTest -Dtest.onlyITs=true verify
56   * -Poracle -pl brmo-loader > /tmp/oracle.log} voor Oracle.
57   *
58   * @author mprins
59   * @todo Deze test draait niet op github omdat er nogal eens een database fout optreed.
60   */
61  @Tag("skip-flakey-pgsql-github")
62  class Brk2StandMutatieGedeeldeStukkenVerwerkingIntegrationTest
63      extends AbstractDatabaseIntegrationTest {
64  
65    private static final Log LOG =
66        LogFactory.getLog(Brk2StandMutatieGedeeldeStukkenVerwerkingIntegrationTest.class);
67    private final Lock sequential = new ReentrantLock(true);
68    private BasicDataSource dsRsgbBrk;
69    private BasicDataSource dsStaging;
70    private BrmoFramework brmo;
71    private IDatabaseConnection staging;
72    private IDatabaseConnection rsgbBrk;
73  
74    static Stream<Arguments> argumentsProvider() {
75      return Stream.of(
76          // "filenames-stand",
77          // "filenames-mutaties",
78          // objectRefs,
79          // rechtenStand,
80          // stukkenStand,
81          // stukdelenStand,
82          // rechtenMutaties,
83          // stukkenMutaties,
84          // stukdelenMutaties,
85          // int aantalKadObjLocatie, int aantalPubliekRBeperking, int aantalOnrndZkBeperking,
86          // int aantalFiliatie
87          arguments(
88              new String[] {
89                "/brk2/stand-53880252670000.anon.xml", "/brk2/stand-53880252170000.anon.xml"
90              },
91              new String[] {
92                "/brk2/mutatie-53880252670000-1.anon.xml", "/brk2/mutatie-53880252170000-1.anon.xml"
93              },
94              Set.of(
95                  "NL.IMKAD.KadastraalObject:53880252670000",
96                  "NL.IMKAD.KadastraalObject:53880252170000"),
97              Set.of(
98                  "NL.IMKAD.ZakelijkRecht:50036403",
99                  "NL.IMKAD.Tenaamstelling:50111282", /*2e*/
100                 "NL.IMKAD.ZakelijkRecht:50036398",
101                 "NL.IMKAD.Tenaamstelling:50111273",
102                 "NL.IMKAD.Aantekening:50007474"),
103             // stukken NL.IMKAD.TIAStuk:20020924000346 en
104             // NL.IMKAD.TIAStuk:20081017002053 worden gedeeld in de stand
105             Stream.of(
106                     "NL.IMKAD.TIAStuk:20020924000346",
107                     "NL.IMKAD.TIAStuk:20081017002053", /*2e*/
108                     "NL.IMKAD.TIAStuk:18011026015603",
109                     "NL.IMKAD.TIAStuk:20020924000346",
110                     "NL.IMKAD.TIAStuk:20081017002053")
111                 .collect(Collectors.toCollection(HashSet::new)),
112             // stukdeel NL.IMKAD.Stukdeel:AKR1.10630844 wordt gedeeld in de stand
113             // stukdeel NL.IMKAD.Stukdeel:1022805638 komt uit 1e bericht/53880252670000
114             Stream.of(
115                     "NL.IMKAD.Stukdeel:1022805638",
116                     "NL.IMKAD.Stukdeel:AKR1.10630844", /*2e*/
117                     "NL.IMKAD.TIAStuk:20081017002053",
118                     "NL.IMKAD.Stukdeel:AKR1.10630844",
119                     "NL.IMKAD.Stukdeel:AKR1.10754757")
120                 .collect(Collectors.toCollection(HashSet::new)),
121             // mutaties
122             Stream.of(
123                     "NL.IMKAD.ZakelijkRecht:50036403",
124                     "NL.IMKAD.Tenaamstelling:1013515840",
125                     "NL.IMKAD.Tenaamstelling:1013515841", /*2*/
126                     "NL.IMKAD.ZakelijkRecht:50036398",
127                     "NL.IMKAD.Tenaamstelling:1013515838",
128                     "NL.IMKAD.Tenaamstelling:1013515839",
129                     "NL.IMKAD.Aantekening:50007474")
130                 .collect(Collectors.toCollection(HashSet::new)),
131             Stream.of(
132                     "NL.IMKAD.TIAStuk:20221117001513", /*2e*/
133                     "NL.IMKAD.TIAStuk:18011026015603",
134                     "NL.IMKAD.TIAStuk:20221117001513")
135                 .collect(Collectors.toCollection(HashSet::new)),
136             Stream.of(
137                     "NL.IMKAD.Stukdeel:500006680324", /*2e*/
138                     "NL.IMKAD.Stukdeel:500006680324",
139                     "NL.IMKAD.Stukdeel:AKR1.10754757")
140                 .collect(Collectors.toCollection(HashSet::new)),
141             2,
142             0,
143             0,
144             2));
145   }
146 
147   @BeforeEach
148   @Override
149   public void setUp() throws Exception {
150     dsStaging = new BasicDataSource();
151     dsStaging.setUrl(params.getProperty("staging.jdbc.url"));
152     dsStaging.setUsername(params.getProperty("staging.user"));
153     dsStaging.setPassword(params.getProperty("staging.passwd"));
154     dsStaging.setAccessToUnderlyingConnectionAllowed(true);
155 
156     dsRsgbBrk = new BasicDataSource();
157     dsRsgbBrk.setUrl(params.getProperty("rsgbbrk.jdbc.url"));
158     dsRsgbBrk.setUsername(params.getProperty("rsgbbrk.user"));
159     dsRsgbBrk.setPassword(params.getProperty("rsgbbrk.passwd"));
160     dsRsgbBrk.setAccessToUnderlyingConnectionAllowed(true);
161 
162     if (this.isOracle) {
163       staging =
164           new DatabaseConnection(
165               OracleConnectionUnwrapper.unwrap(dsStaging.getConnection()),
166               params.getProperty("staging.user").toUpperCase());
167       staging
168           .getConfig()
169           .setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new Oracle10DataTypeFactory());
170       staging.getConfig().setProperty(DatabaseConfig.FEATURE_SKIP_ORACLE_RECYCLEBIN_TABLES, true);
171 
172       rsgbBrk =
173           new DatabaseConnection(
174               OracleConnectionUnwrapper.unwrap(dsRsgbBrk.getConnection()),
175               params.getProperty("rsgbbrk.schema").toUpperCase());
176       rsgbBrk
177           .getConfig()
178           .setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new Oracle10DataTypeFactory());
179       rsgbBrk.getConfig().setProperty(DatabaseConfig.FEATURE_SKIP_ORACLE_RECYCLEBIN_TABLES, true);
180     } else if (this.isPostgis) {
181       staging = new DatabaseDataSourceConnection(dsStaging);
182       staging
183           .getConfig()
184           .setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new PostgresqlDataTypeFactory());
185       rsgbBrk = new DatabaseDataSourceConnection(dsRsgbBrk, params.getProperty("rsgbbrk.schema"));
186       rsgbBrk
187           .getConfig()
188           .setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new PostgresqlDataTypeFactory());
189     }
190 
191     brmo = new BrmoFramework(dsStaging, null, dsRsgbBrk);
192 
193     FlatXmlDataSetBuilder fxdb = new FlatXmlDataSetBuilder();
194     fxdb.setCaseSensitiveTableNames(false);
195     IDataSet stagingDataSet =
196         fxdb.build(
197             new FileInputStream(
198                 new File(
199                     Objects.requireNonNull(
200                             Brk2StandMutatieGedeeldeStukkenVerwerkingIntegrationTest.class
201                                 .getResource("/staging-empty-flat.xml"))
202                         .toURI())));
203 
204     sequential.lock();
205     DatabaseOperation.CLEAN_INSERT.execute(staging, stagingDataSet);
206     // CleanUtil.cleanRSGB_BRK2(rsgbBrk);
207 
208     assumeTrue(
209         0L == brmo.getCountBerichten(BrmoFramework.BR_BRK2, "STAGING_OK"),
210         "Er zijn geen STAGING_OK berichten");
211     assumeTrue(
212         0L == brmo.getCountLaadProcessen(BrmoFramework.BR_BRK2, "STAGING_OK"),
213         "Er zijn geen STAGING_OK laadprocessen");
214   }
215 
216   @AfterEach
217   void cleanup() throws Exception {
218     brmo.closeBrmoFramework();
219 
220     CleanUtil.cleanSTAGING(staging, false);
221     CleanUtil.cleanRSGB_BRK2(rsgbBrk);
222     staging.close();
223     dsStaging.close();
224     rsgbBrk.close();
225     dsRsgbBrk.close();
226 
227     sequential.unlock();
228   }
229 
230   @DisplayName("BRK2 XML in staging laden en transformeren, daarna mutaties toepassen")
231   @ParameterizedTest(name = "testBerichten #{index}: object refs: {1}")
232   @MethodSource("argumentsProvider")
233   void testBerichten(
234       String[] bestandNamen,
235       String[] mutatieBestandNamen,
236       Set<String> objectRefs,
237       Set<String> rechtenStand,
238       Set<String> stukkenStand,
239       Set<String> stukdelenStand,
240       Set<String> rechtenMutaties,
241       Set<String> stukkenMutaties,
242       Set<String> stukdelenMutaties,
243       int aantalKadObjLocatie,
244       int aantalPubliekRBeperking,
245       int aantalOnrndZkBeperking,
246       int aantalFiliatie)
247       throws Exception {
248 
249     final boolean isPerceel = objectRefs.iterator().next().endsWith("0000");
250 
251     assumeFalse(
252         null
253             == Brk2StandMutatieGedeeldeStukkenVerwerkingIntegrationTest.class.getResource(
254                 bestandNamen[0]),
255         () -> "Het test bestand '" + bestandNamen[0] + "' moet er zijn.");
256 
257     // stand bericht laden
258     bestandenLadenEnValideren(objectRefs, 0, bestandNamen);
259     // voor stand, maar op volgorde van database
260     brmo.setOrderBerichten(false);
261     //        brmo.setEnablePipeline(true);
262     //        brmo.setTransformPipelineCapacity(2);
263     //        brmo.setBatchCapacity(1);
264     //        brmo.setLimitStandBerichtenToTransform(1);
265     transformerenEnValideren(bestandNamen.length);
266 
267     // controle BRK inhoud stand
268     ITable recht = rsgbBrk.createDataSet().getTable("recht");
269     checkIdentificatiesEnAantal(recht, rechtenStand);
270 
271     ITable stuk = rsgbBrk.createDataSet().getTable("stuk");
272     checkIdentificatiesEnAantal(stuk, stukkenStand);
273 
274     ITable stukdeel = rsgbBrk.createDataSet().getTable("stukdeel");
275     checkIdentificatiesEnAantal(stukdeel, stukdelenStand);
276 
277     ITable onroerendezaak = rsgbBrk.createDataSet().getTable("onroerendezaak");
278     checkIdentificatiesEnAantal(onroerendezaak, objectRefs);
279 
280     // mutatie bericht(en) laden
281     brmo.setOrderBerichten(true);
282     bestandenLadenEnValideren(objectRefs, bestandNamen.length, mutatieBestandNamen);
283     transformerenEnValideren(bestandNamen.length + mutatieBestandNamen.length);
284 
285     // BRK inhoud mutaties valideren
286     onroerendezaak = rsgbBrk.createDataSet().getTable("onroerendezaak");
287     checkIdentificatiesEnAantal(onroerendezaak, objectRefs);
288 
289     ITable onroerendezaak_archief = rsgbBrk.createDataSet().getTable("onroerendezaak_archief");
290     checkIdentificatiesEnAantal(onroerendezaak_archief, objectRefs);
291 
292     recht = rsgbBrk.createDataSet().getTable("recht");
293     checkIdentificatiesEnAantal(recht, rechtenMutaties);
294 
295     ITable recht_archief = rsgbBrk.createDataSet().getTable("recht_archief");
296     checkIdentificatiesEnAantal(recht_archief, rechtenStand);
297 
298     stuk = rsgbBrk.createDataSet().getTable("stuk");
299     // van stuk geen archief tabel, dus stand erbij nemen
300     stukkenMutaties.addAll(stukkenStand);
301     checkIdentificatiesEnAantal(stuk, stukkenMutaties);
302 
303     stukdeel = rsgbBrk.createDataSet().getTable("stukdeel");
304     // van stukdeel geen archief tabel, dus stand erbij nemen
305     stukdelenMutaties.addAll(stukdelenStand);
306     checkIdentificatiesEnAantal(stukdeel, stukdelenMutaties);
307 
308     ITable publiekrechtelijkebeperking =
309         rsgbBrk.createDataSet().getTable("publiekrechtelijkebeperking");
310     assertEquals(
311         aantalPubliekRBeperking,
312         publiekrechtelijkebeperking.getRowCount(),
313         "Aantal publiekrechtelijkebeperking klopt niet");
314 
315     ITable onroerendezaakbeperking = rsgbBrk.createDataSet().getTable("onroerendezaakbeperking");
316     ITable onroerendezaakbeperking_archief =
317         rsgbBrk.createDataSet().getTable("onroerendezaakbeperking_archief");
318     assertEquals(
319         aantalOnrndZkBeperking,
320         onroerendezaakbeperking.getRowCount(),
321         "Aantal onroerendezaakbeperking klopt niet");
322 
323     ITable onroerendezaakfiliatie = rsgbBrk.createDataSet().getTable("onroerendezaakfiliatie");
324     assertEquals(
325         aantalFiliatie,
326         onroerendezaakfiliatie.getRowCount(),
327         "Aantal onroerendezaakfiliatie klopt niet");
328     // check dat alle records de objectRef als "onroerendezaak" hebben
329     String onroerendezaakRef;
330     for (int i = 0; i < onroerendezaakfiliatie.getRowCount(); i++) {
331       onroerendezaakRef = onroerendezaakfiliatie.getValue(i, "onroerendezaak").toString();
332       assertTrue(
333           objectRefs.contains(onroerendezaakRef),
334           "onroerendezaakfiliatie.onroerendezaak "
335               + onroerendezaakRef
336               + " is niet gelijk aan objectRef");
337     }
338     //    ITable onroerendezaakfiliatie_archief =
339     //            rsgbBrk.createDataSet().getTable("onroerendezaakfiliatie_archief");
340     //    for (int i = 0; i < onroerendezaakfiliatie_archief.getRowCount(); i++) {
341     //      onroerendezaakRef = onroerendezaakfiliatie_archief.getValue(i,
342     // "onroerendezaak").toString();
343     //      assertTrue(
344     //          objectRefs.contains(onroerendezaakRef),
345     //          "onroerendezaakfiliatie_archief.onroerendezaak "
346     //              + onroerendezaakRef
347     //              + " is niet gelijk aan objectRef");
348     //    }
349 
350     ITable perceelOfAppRe;
351     ITable perceelOfAppRe_archief;
352     if (isPerceel) {
353       perceelOfAppRe = rsgbBrk.createDataSet().getTable("perceel");
354       perceelOfAppRe_archief = rsgbBrk.createDataSet().getTable("perceel_archief");
355       assertAll(
356           "perceel geometrie",
357           () ->
358               assertNotNull(
359                   perceelOfAppRe.getValue(0, "begrenzing_perceel"),
360                   "Perceel begrenzing geometrie is 'null'"),
361           () ->
362               assertNotNull(
363                   perceelOfAppRe.getValue(0, "plaatscoordinaten"),
364                   "Plaatscoordinaten geometrie is 'null'"),
365           () ->
366               assertNotNull(
367                   perceelOfAppRe_archief.getValue(0, "begrenzing_perceel"),
368                   "Perceel begrenzing geometrie is 'null'"),
369           () ->
370               assertNotNull(
371                   perceelOfAppRe_archief.getValue(0, "plaatscoordinaten"),
372                   "Plaatscoordinaten geometrie is 'null'"));
373     } else {
374       perceelOfAppRe = rsgbBrk.createDataSet().getTable("appartementsrecht");
375       perceelOfAppRe_archief = rsgbBrk.createDataSet().getTable("appartementsrecht_archief");
376     }
377     checkIdentificatiesEnAantal(perceelOfAppRe, objectRefs);
378     checkIdentificatiesEnAantal(perceelOfAppRe_archief, objectRefs);
379 
380     //        ITable aantekeningrecht =
381     // rsgbBrk.createDataSet().getTable("recht_aantekeningrecht");
382     //        ITable isbelastmet = rsgbBrk.createDataSet().getTable("recht_isbelastmet");
383     //        ITable isbeperkttot = rsgbBrk.createDataSet().getTable("recht_isbeperkttot");
384 
385     //        ITable aantekeningrecht_archief =
386     // rsgbBrk.createDataSet().getTable("recht_aantekeningrecht_archief");
387     //        ITable isbelastmet_archief =
388     // rsgbBrk.createDataSet().getTable("recht_isbelastmet_archief");
389     //        ITable isbeperkttot_archief =
390     // rsgbBrk.createDataSet().getTable("recht_isbeperkttot_archief");
391 
392     //        ITable persoon = rsgbBrk.createDataSet().getTable("persoon");
393     //        ITable natuurlijkpersoon = rsgbBrk.createDataSet().getTable("natuurlijkpersoon");
394     //        ITable nietnatuurlijkpersoon =
395     // rsgbBrk.createDataSet().getTable("nietnatuurlijkpersoon");
396     //        ITable adres = rsgbBrk.createDataSet().getTable("adres");
397 
398     ITable objectlocatie = rsgbBrk.createDataSet().getTable("objectlocatie");
399     ITable objectlocatie_archief = rsgbBrk.createDataSet().getTable("objectlocatie_archief");
400     assertAll(
401         "objectlocatie",
402         () ->
403             assertEquals(
404                 aantalKadObjLocatie,
405                 objectlocatie.getRowCount(),
406                 "Het aantal objectlocaties is niet als verwacht."),
407         () -> {
408           // check dat alle records de objectRef als "heeft" hebben
409           for (int i = 0; i < objectlocatie.getRowCount(); i++) {
410             assertTrue(
411                 objectRefs.contains(objectlocatie.getValue(i, "heeft")),
412                 "objectlocatie.heeft is niet gelijk aan objectRef");
413           }
414         },
415         () -> {
416           for (int i = 0; i < objectlocatie_archief.getRowCount(); i++) {
417             assertTrue(
418                 objectRefs.contains(objectlocatie_archief.getValue(i, "heeft")),
419                 "objectlocatie.heeft is niet gelijk aan objectRef");
420           }
421         });
422   }
423 
424   /**
425    * Check of de identificaties van de objecten in een tabel gelijk zijn aan de verwachte
426    * identificaties.
427    *
428    * @param tableToCheck de te controleren tabel
429    * @param expectedIdentificaties de verwachte identificaties (nromaal ook primary keys)
430    * @throws Exception if any
431    */
432   private void checkIdentificatiesEnAantal(ITable tableToCheck, Set<String> expectedIdentificaties)
433       throws Exception {
434     assertEquals(
435         expectedIdentificaties.size(),
436         tableToCheck.getRowCount(),
437         () ->
438             "Het aantal records in de tabel "
439                 + tableToCheck.getTableMetaData().getTableName()
440                 + " is niet gelijk aan het aantal verwachte identificaties");
441     for (int i = 0; i < tableToCheck.getRowCount(); i++) {
442       String identificatie = (String) tableToCheck.getValue(i, "identificatie");
443       assertTrue(
444           expectedIdentificaties.contains(identificatie),
445           () ->
446               "identificatie "
447                   + identificatie
448                   + " komt niet voor in "
449                   + tableToCheck.getTableMetaData().getTableName());
450     }
451   }
452 
453   private void transformerenEnValideren(int expected) throws BrmoException, InterruptedException {
454     LOG.info(
455         "Transformeren berichten naar rsgb DB met optie 'orderberichten': "
456             + brmo.isOrderBerichten());
457     Thread t = brmo.toRsgb();
458     t.join();
459 
460     List<Bericht> berichten = brmo.listBerichten();
461     if (LOG.isInfoEnabled()) {
462       berichten.forEach(b -> LOG.debug(b.toString()));
463     }
464 
465     assertEquals(
466         expected,
467         brmo.getCountBerichten(BrmoFramework.BR_BRK2, "RSGB_OK"),
468         "Niet alle berichten zijn OK getransformeerd.");
469 
470     berichten.forEach(
471         b -> {
472           assertNotNull(b, "Bericht is 'null'");
473           assertNotNull(b.getDbXml(), "'db-xml' van bericht is 'null'");
474         });
475   }
476 
477   /**
478    * laden en valideren van brk 2 bestand(en).
479    *
480    * @param objectRefs objectRefs van de te laden berichten
481    * @param eerderGeladen aantal eerder geladen berichten (uit stand bijv.)
482    * @param bestandsNamen 1 of meer berichten
483    * @throws Exception if any
484    */
485   private void bestandenLadenEnValideren(
486       Set<String> objectRefs, int eerderGeladen, String... bestandsNamen) throws Exception {
487     int aantal = bestandsNamen.length + eerderGeladen;
488 
489     for (String bestandsNaam : bestandsNamen) {
490       LOG.info("Laden van " + bestandsNaam + " bericht in staging DB.");
491       brmo.loadFromFile(
492           BrmoFramework.BR_BRK2,
493           Objects.requireNonNull(
494                   Brk2StandMutatieGedeeldeStukkenVerwerkingIntegrationTest.class.getResource(
495                       bestandsNaam))
496               .getFile(),
497           null);
498     }
499 
500     assertEquals(
501         aantal,
502         brmo.getCountLaadProcessen(BrmoFramework.BR_BRK2, "STAGING_OK"),
503         "Het aantal laadprocessen is niet correct.");
504     List<LaadProces> processen = brmo.listLaadProcessen();
505     assertNotNull(processen, "De verzameling processen bestaat niet.");
506     assertEquals(aantal, processen.size(), "Het aantal processen is niet 1.");
507 
508     List<Bericht> berichten = brmo.listBerichten();
509     assertFalse(berichten.isEmpty(), "De verzameling berichten bestaat niet.");
510     assertEquals(aantal, berichten.size(), "Het aantal berichten is niet correct.");
511 
512     for (Bericht b : berichten) {
513       assertAll(
514           "bericht",
515           () -> assertNotNull(b, "Bericht is 'null'"),
516           () -> assertNotNull(b.getBrXml(), "'br_xml' van bericht is 'null'"),
517           () ->
518               assertTrue(
519                   objectRefs.contains(b.getObjectRef()),
520                   "Het bericht uit de database heeft niet de juiste objectRef."));
521     }
522   }
523 }