Test utilities, or set-up methods considered harmful
Tags: unittest, tdd, java, junit
Published: 2023-11-14 18:58:13

---
title: Test utilities, or set-up methods considered harmful
published: true
description: Have you ever felt your set-up/tear-down methods are getting really obscure? They may very well be. Test utilities are a great alternative!

tags: unittest, tdd, java, junit
cover_image: https://upload.wikimedia.org/wikipedia/commons/thumb/4/49/Six_workers_on_crane_in_Shibuya.jpg/1280px-Six_workers_on_crane_in_Shibuya.jpg
# Use a ratio of 100:42 for best results.
---

One of the most interesting learnings I had in the old SEA Tecnologia is the creation of test utilities .

Test utilities are a way to reuse code in unit tests. Usually, this is done using `setUp`or `@Before` methods, but this has some disadvantages. For example, in a test case, we can have the following initialization:

```java
private Address address;
private AddressDAO addressDAO;

@Before
public void setUp() {
    address = new Address();
    address.setStreet("Rua fulano");
    address.setNumber("123/A");
    addressDAO = new AddressDAO();
}
```

This initialization works well in the test below...

```java
@Test
public void testGetAllAddresses(){
    addressDAO.addAddress(address);

    List<Address> addresses = addressDAO.getAllAddresses();

    assertEquals(1, addresses.size());
    assertEquals("Rua fulano", addresses.get(0).getStreet());
    assertEquals("123/A", addresses.get(0).getNumber());
}
```

However, in the following test, the created object is a waste, is not used at all:

```java
@Test
public void testGetNoAddress() {
    List<Address> addresses = addressDAO.getAllAddresses();

    assertEquals(0, addresses.size());
}
```

In the next following test, we have code redundancy. We also have to decide whether the other object should be created in the `@Before` method or in the test method:

```java
@Test
public void testGetAllAddressesMoreThanOne() {
    addressDAO.addAddress(address);
    Address address2 = new Address();
    address2.setStreet("Outra rua");
    address2.setNumber("111");
    addressDAO.addAddress(address2);
    List<Address> addresses = addressDAO.getAllAddresses();
    assertEquals(1, addresses.size());
    assertEquals("Rua fulano", addresses.get(0).getStreet());
    assertEquals("123/A", addresses.get(0).getNumber());
}
```

These inconveniences are minor when compared to the task of creating a network of dependencies. For example, to test a class `Person` that adds a test case `Address` in another test case, we will have to have one `@Before` similar to this:

```java
private Person person;
private Address address;
private PersonDAO personDAO;

@Before
public void setUp() {
    address = new Address();
    address.setStreet("Rua fulano");
    address.setNumber("123/A");
    person = new Person();
    person.setName("João");
    person.setAddress(address);
    personDAO = new PersonDAO();
}
```

The code for creating addresses was duplicated, and it is difficult to create the dependencies. In these examples, we see simple cases, but it is easy to see how the situation would get complicated.

We solve this problem by writing a class to create these objects. This class would be something like this:

```java
public class TestUtil {
    public static Address utilCreateAddress(String street, String number) {
        Address address = new Address();
        address.setStreet("Rua fulano");
        address.setNumber("123/A");
        return address;
    }

    public static Person utilCreatePerson(String name, Address address) {
        Person person = new Person();
        person.setName(name);
        person.setAddress(address);
        return person;
    }
}
```

Our test cases extended `TestUtil`, making object creation easier:

```java
public class TestAddress2 extends TestUtil {
    private AddressDAO addressDAO = new AddressDAO();

    @Test
    public void testGetAllAddresses() {
        Address address = utilCreateAddress("Rua fulano", "123/A");
        addressDAO.addAddress(address);

        List<Address> addresses = addressDAO.getAllAddresses();

        assertEquals(1, addresses.size());
        assertEquals("Rua fulano", addresses.get(0).getStreet());
        assertEquals("123/A", addresses.get(0).getNumber());
    }

    @Test
    public void testGetNoAddress() {
        List<Address> addresses = addressDAO.getAllAddresses();

        assertEquals(0, addresses.size());
    }

    @Test
    public void testGetAllAddressesMoreThanOne() {
        Address address = utilCreateAddress("Rua fulano", "123/A");
        Address address2 = utilCreateAddress("Outra rua", "111");
        addressDAO.addAddress(address);
        addressDAO.addAddress(address2);

        List<Address> addresses = addressDAO.getAllAddresses();

        assertEquals(2, addresses.size());
        assertEquals("Rua fulano", addresses.get(0).getStreet());
        assertEquals("123/A", addresses.get(0).getNumber());
    }
}
```

As we also frequently needed some specific object with just one or two parameters to be defined, we created methods variants:

```java
public static Address utilCreateAddress() {
    return utilCreateAddress("Qualquer", "Qualquer");
}

public static Person utilCreatePerson() {
    return utilCreatePerson("José", utilCreateAddress());
}
```

We learned that in a somewhat complex project, with large networks of object dependencies. The use of these test utilities made it possible to practice [TDD](https://translate.google.com/website?sl=pt&tl=en&hl=pt-BR&client=webapp&u=https://web.archive.org/web/20100806130712/http://pt.wikipedia.org/wiki/Test_Driven_Development) on the system. It was exciting to discover that, to create that document that depended on seven other documents and five or six users, all you had to do was call a method.

Of course, there is more to our testing utilities than has been written here, and there may be even more that we haven't even done. (For example, it may be interesting to write test utilities for specific classes, instead of one gigantic utility.) However, as the idea is very simple, we hope this first step motivates you to think about the topic. Until later!

*(This post was originally published as  "[Test Utilities, or set-up methods considered harmful](https://suspensao.blog.br/disbelief/test-utilities)" in [Suspension of Disbelief](https://suspensao.blog.br/disbelief/). It was originally posted in an [former employer's blog](https://translate.google.com/website?sl=pt&tl=en&hl=pt-BR&client=webapp&u=https://web.archive.org/web/20100806130712/http://blog.seatecnologia.com.br:80/2010/05/20/utilitirios-de-teste). As the original post went offline but the topic remains relevant, I decided to republish it.)*