Search code examples
javajunit5sonarlint

Best way to unit test mapper for huge java object with junit 5


I need to unit test a mapper for a 30 arguments object, however SonarLint recommendation is to remain under 25 assertions for a single test. Is there a way to test my mapper without making two tests ?

Here is my test :

@Test
void devraitConvertireEnApercu() {

        //creation of documentConventionOTD with all fields

        ApercuConvention ressource = mappeur.p2r(documentConventionOTD);

        assertAll(
                () -> assertNotNull(ressource),
                () -> assertNotNull(ressource),
                () -> assertEquals(documentConventionOTD.getIdConvention(), ressource.getId()),
                () -> assertEquals(documentConventionOTD.getTypeConvention(), ressource.getTypeConvention()),
                () -> assertEquals(documentConventionOTD.getCodeGeo(), ressource.getCodeGeo()),
                () -> assertEquals(documentConventionOTD.getOrganismeFormation(), ressource.getOrganismeFormation()),
                () -> assertEquals(documentConventionOTD.getIntituleFormation(), ressource.getIntituleFormation()),

                () -> assertEquals(documentConventionOTD.getCodePostalLieuFormation(), ressource.getCodePostal()),
                () -> assertEquals(documentConventionOTD.getVilleLieuFormation(), ressource.getVille()),
                () -> assertEquals(documentConventionOTD.getDateDebutConvention(), ressource.getDateDebut()),
                () -> assertEquals(documentConventionOTD.getNbPlaces(), ressource.getNbPlaces()),
                () -> assertEquals(documentConventionOTD.getMontantBDCInitial(), ressource.getMontantBDCInitial()),

                () -> assertEquals(documentConventionOTD.getDateBDCInitial(), ressource.getDateBDCInitial()),
                () -> assertEquals(documentConventionOTD.getMontantBDCRectificatif(), ressource.getMontantBDCRectificatif()),
                () -> assertEquals(documentConventionOTD.getDateBDCRectificatif(), ressource.getDateBDCRectificatif()),
                () -> assertEquals(documentConventionOTD.getMontantTotalAvance(), ressource.getMontantTotalAvance()),
                () -> assertEquals(documentConventionOTD.getEstAvanceDemandee(), ressource.getEstAvanceDemandee()),

                () -> assertEquals(documentConventionOTD.getDateCalculAvance(), ressource.getDateCalculAvance()),
                () -> assertEquals(documentConventionOTD.getEstBeneficiaireAvanceActif(), ressource.getEstBeneficiaireAvanceActif()),
                () -> assertEquals(documentConventionOTD.getEtatRapprochement(), ressource.getEtatRapprochement()),
                () -> assertEquals(documentConventionOTD.getDateAlerteBDCGenere(), ressource.getDateAlerteBDCGenere()),
                () -> assertEquals(documentConventionOTD.getEstTraiteeAlerteBDCGenere(), ressource.getEstTraiteeAlerteBDCGenere()),

                () -> assertEquals(documentConventionOTD.getDateAlerteBDCNonGenere(), ressource.getDateAlerteBDCNonGenere()),
                () -> assertEquals(documentConventionOTD.getEstTraiteeAlerteBDCNonGenere(), ressource.getEstTraiteeAlerteBDCNonGenere()),
                () -> assertEquals(documentConventionOTD.getDateAlertePrixTotal(), ressource.getDateAlertePrixTotal()),
                () -> assertEquals(documentConventionOTD.getEstTraiteeAlertePrixTotal(), ressource.getEstTraiteeAlertePrixTotal()),

                () -> assertEquals(documentConventionOTD.getDateAlerteNombrePlaceAchetees(), ressource.getDateAlerteNombrePlaceAchetees()),
                () -> assertEquals(documentConventionOTD.getEstTraiteeAlerteNombrePlaceAchetees(), ressource.getEstTraiteeAlerteNombrePlaceAchetees()),
                () -> assertEquals(documentConventionOTD.getNumeroBonReservation(), ressource.getNumeroBonReservation()),
                () -> assertEquals(documentConventionOTD.getCodeTypeSession(), ressource.getTypeSession())
        );


    }

Solution

  • Personally, I wouldn't bother with checking the number of assertions, since, sure, it's best if the unit test remains compact, but what's the test worth, if it doesn't test all it should test?

    Two approaches jump to mind.

    Let's say you have a Person class, which has a few fields (I'm not going to go for thirty asserts), but you are limited to one assertion per test.

    public class Person {
      private String name;
      private Date birthDay;
    
      public Person(String name, Date birthDay) {
        this.name = name;
        this.birthDay = birthDay;
      }
    
      public String getName() { return name; }
    
      public Date getBirthDate() { return birthDay; }
    
      public boolean isAdult() { /* assume implemented */ }
    }
    

    Approach 1 - several tests:

    public class PersonTest {
    
     @Test
     public void testName() {
       assertEquals("Name should be Sam", "Sam", buildPerson().getName());
     }
    
     @Test
     public void testAdult() {
       assertTrue("Person should be an adult", buildPerson().isAdult());
     }
    
      public Person buildPerson() {
        return new Person("Sam", createDateFrom20YearsAgo());
      }
    }
    

    So, this honors your limitation, but this might be a big overkill for your thirty assertions.

    You can also perform the actual testing in a separate method. Personally, I don't really see an upside to this, but it would help you limit your number of assertions:

    public class PersonTest {
    
       @Test
       public void testPerson() {
         Person p = buildPerson();
         String result = comparePersonToExpectations(p, "Sam", true);
         assertEquals(result, "", result);
       }
    
       public String comparePersonToExpectations(Person person, String expectedName, boolean shouldBeAdult) {
         if ( !expectedName.equals(person.getName())
           return "Name should be: " + expectedName + " but was: " + person.getName();
         if ( shouldBeAdult != person.isAdult()) 
           return "AdultCheck expected: " + shouldBeAdult + ", Actual: " + person.isAdult();
         return "";
       }
    
       public Person buildPerson() {
         return new Person("Sam", createDateFrom20YearsAgo());
       }
    }