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);
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.