Search code examples
javabuilderlombok

How to use Lombok @Builder annotation on Methods


I want to have an easy way to construct test data and have found the Builder pattern to be a good fit as described here. However to reduce boilerplate codes in the component tests, even more, I have found @Builder from Project Lombok to be a nice candidate to try. However, I can't find any documentation or online examples on how to use it on a method. I want to use @Builder on some sort of factory method since I can't make any changes to the implementation.

Can someone give an example on how to actually use @Builder on a method?


Solution

  • Using @Builder on method to create a Dog and Cat instance.

    In this example @Value creates a final immutable value object with accessor methods (getters), an all args constructor, equals(), hashCode() and toString().

    import static org.junit.Assert.*;
    import lombok.Builder;
    import lombok.Value;
    
    import org.junit.Test;
    
    @SuppressWarnings("javadoc")
    public class ImmutableAnimals {
    
        @Builder(builderMethodName = "dogBuilder")
        public static Dog newDog(String color, String barkSound) {
            return new Dog(color, barkSound);
        }
    
        @Builder(builderMethodName = "catBuilder")
        public static Cat newCat(String color, String meowSound) {
            return new Cat(color, meowSound);
        }
    
        public static interface Animal {
            String getColor();
        }
    
        @Value
        public static class Cat implements Animal {
            String color;
            String meowSound;
        }
    
        @Value
        public static class Dog implements Animal {
            String color;
            String barkSound;
        }
    
        @Test
        public void testDog() {
            final String expectedBarkSound = "woof";
            final String expectedColor = "brown";
    
            final Dog dog = ImmutableAnimals.dogBuilder()
                .barkSound(expectedBarkSound)
                .color(expectedColor)
                .build();
    
            assertEquals(expectedBarkSound, dog.getBarkSound());
            assertEquals(expectedColor, dog.getColor());
        }
    
        @Test
        public void testCat() {
            final String expectedMeowSound = "purr";
            final String expectedColor = "white";
    
            final Cat cat = ImmutableAnimals.catBuilder()
                .meowSound(expectedMeowSound)
                .color(expectedColor)
                .build();
    
            assertEquals(expectedMeowSound, cat.getMeowSound());
            assertEquals(expectedColor, cat.getColor());
        }
    }
    

    Here's another example with the same domain classes but using mutable values. However, as always favor immutability whenever possible.

    import static org.junit.Assert.*;
    import lombok.Builder;
    import lombok.Data;
    
    import org.junit.Test;
    
    @SuppressWarnings("javadoc")
    public class MutableAnimals {
    
        @Builder(builderMethodName = "dogBuilder")
        public static Dog newDog(String color, String barkSound) {
            final Dog dog = new Dog();
            dog.setBarkSound(barkSound);
            dog.setColor(color);
            return dog;
        }
    
        @Builder(builderMethodName = "catBuilder")
        public static Cat newCat(String color, String meowSound) {
            final Cat cat = new Cat();
            cat.setMeowSound(meowSound);
            cat.setColor(color);
            return cat;
        }
    
        public static interface Animal {
            String getColor();
        }
    
        @Data
        public static class Cat implements Animal {
            String color;
            String meowSound;
        }
    
        @Data
        public static class Dog implements Animal {
            String color;
            String barkSound;
        }
    
        @Test
        public void testDog() {
            final String expectedBarkSound = "woof";
            final String expectedColor = "brown";
    
            final Dog dog = MutableAnimals.dogBuilder()
                .barkSound(expectedBarkSound)
                .color(expectedColor)
                .build();
    
            assertEquals(expectedBarkSound, dog.getBarkSound());
            assertEquals(expectedColor, dog.getColor());
        }
    
        @Test
        public void testCat() {
            final String expectedMeowSound = "purr";
            final String expectedColor = "white";
    
            final Cat cat = MutableAnimals.catBuilder()
                .meowSound(expectedMeowSound)
                .color(expectedColor)
                .build();
    
            assertEquals(expectedMeowSound, cat.getMeowSound());
            assertEquals(expectedColor, cat.getColor());
        }
    }