Easier mocks with data

I have a love/hate relationship with mocks in unit tests. They are wonderful to mock out services, but building mocks or objects with just enough data for testing is often a pain. I end up writing code like:

Person person = new Person();
person.setName("John Doe");
person.setLocation("Brussels");
Organization organization = new Organization();
organizaion.setName("Company Ltd");
person.setOrganization(organization);

I believe this is too verbose to be nice. As such test objects are often needed this code may be moved to a separate class to build test mother objects. This arguably makes things worse by hiding the values used and more or less forcing all tests to use the same field values.

When I need this object to be a Mockito mock it becomes something like this:

Person person = Mockito.mock(Person.class);
when(person.getName()).thenReturn("John Doe");
when(person.getLocation()).thenReturn("Brussels");
Organization organization = mock(Organization.class);
when(organizaion.getName()).thenReturn("Company Ltd");
when(person.getOrganization()).thenReturn(organization);

This is not very readable.

Taking inspiration from faker gems in Ruby, I created a new library to make this more legible.

Person person = FakerMock.withFields(Person.class,
        "name", "John Doe",
        "location", "Brussels",
        "organization", FakerMock.withFields(Organization.class, 
                "name", "Company Ltd"));

This is now available as jFaker.

This is a reasonable simple start, but I would like to extend this to also support javabeans (same syntax but using FakerBean instead of FakerMock) and also te be able to have values read from a yaml file. In that case, I would probably use a syntax like

FakerBuilder faker = new FakerBuilder().
        withYaml("my/yaml/file/with/general/defaults.yml");
        withYaml("my/yaml/file/with/defaults/for/this/test.yml");
Person person = faker.withFields(Person.class,
        "name", "John Doe",
        "location", "Brussels",
        "organization", faker.withFields(Organization.class, 
                "name", "Company Ltd"));

Would this be useful for you?

511 Comments

  1. balder says:

    can be usefull, but it’s a bit as org.springframework.test.util.ReflectionUtils

    The main issue I have with this type of things is that you have to lookup the field names instead of autocomplete with setter. And also refactoring can be a bit of pain.

    So I probably would stick to a builder (Lombok!!) or setter or withers.

Leave a Reply

Your email address will not be published. Required fields are marked *

question razz sad evil exclaim smile redface biggrin surprised eek confused cool lol mad twisted rolleyes wink idea arrow neutral cry mrgreen

*