Search code examples
javaspringunit-testing

Unit tests - good practice when comparing object fields


I am writing unit tests for my web application. I started to wonder if what I am writing is a good practice. I mean when an object creates a snapshot of its state and I compare the field values of the newly created object to determine whether they are correct.

  @Test
    public void testCreateUserSnapshotWithInitializedUser() {
        //given
        User user = aUser()
                .withUsername("Test")
                .withPassword("Pa$$word")
                .withEmail("[email protected]")
                .withRole(UserRole.COMMON)
                .buildInitialized();

        //when
        UserSnapshot snapshot = user.createSnapshot();

        //then
        assertEquals("Test", snapshot.getUsername());
        assertEquals("Pa$$word", snapshot.getPassword());
        assertEquals("[email protected]", snapshot.getEmail());
        assertEquals(UserRole.COMMON, snapshot.getRole());
        assertEquals(true, snapshot.isEnabled());
    }

Is the amount of assertion in the then section is too overwhelming? Or should I separate appropriate methods for each asseration e.g.

assertUsernameIs("Test", snapshot);

Or create one method like: assertSnapshotIsCorrect(snapshot);


Solution

  • If you wanna validate all the parameters, to reduce the number of assertions, you can map the object to String before asserting.

    I usually made a class utils to do this mapping, like that:

    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class TestUtils {
    
        public static ObjectMapper mapper = new ObjectMapper();
    
        public static String mapToString(Object object) throws JsonProcessingException {
            return mapper.writeValueAsString(object);
        }
    }
    

    And then you can assert only once comparing the result and one previously build mock object:

    @Test
    void testCreateUserSnapshotWithInitializedUser() {
        UserSnapshot mock = UserSnapshotMocks.createUserSnapshot();
    
        var result = testCreateUserSnapshotWithInitializedUser(user);
        assertEquals(TestUtils.mapToString(mock), TestUtils.mapToString(result));
    }
    

    This way you will assert the entire object like one and only String.