Kohei Nozaki's blog 

Favor composition over inheritance


Posted on Friday Aug 14, 2020 at 04:52PM in Technology


In this entry, I’ll discuss problems of inheritance, which is often overused in software written in an object oriented programming language, and how we can do better with composition, which is usually a much better alternative to inheritance.

Inheritance can make your code fragile

Let’s think about some piece of software used by some cafe. It contains the following classes:

1e95a7ea 3a54 4fcc ad6b 798b5b3d1ebf

There is an interface called Beverage, which can return the price and description of a beverage. Most probably there are Coffee or Tea classes that implement the interface. And there is a class called Order, where you can add Beverage objects to it in order to calculate the grand total on the bill for a customer of the cafe. The code of these looks like this:

interface Beverage {
    BigDecimal price();
    String description();
}

class Order {

    private static final BigDecimal TAX_RATE = new BigDecimal("0.1");
    private BigDecimal subTotal = BigDecimal.ZERO;

    void add(Beverage beverage) {
        subTotal = subTotal.add(beverage.price());
    }

    void addAll(Collection<? extends Beverage> beverages) {
        for (Beverage beverage : beverages)
            subTotal = subTotal.add(beverage.price());
    }

    BigDecimal grandTotal() {
        BigDecimal tax = subTotal.multiply(TAX_RATE);
        return subTotal.add(tax);
    }
}

Now, let’s consider the following scenario: the owner of the cafe wants to start a campaign to boost their sales. The idea of the campaign is that if a customer orders more than 2 beverages at the same time, he/she will get 20% discount from the grand total. In order to implement this requirement, a programmer comes up with the CampaignOrder class which extends the Order class. It looks like the following:

class CampaignOrder extends Order {

    private static final BigDecimal DISCOUNT_RATE = new BigDecimal("0.2");
    private int numberOfBeverages;

    @Override
    void add(Beverage beverage) {
        super.add(beverage);
        numberOfBeverages++;
    }

    @Override
    void addAll(Collection<? extends Beverage> beverages) {
        super.addAll(beverages);
        numberOfBeverages += beverages.size();
    }

    @Override
    BigDecimal grandTotal() {
        BigDecimal grandTotal = super.grandTotal();
        if (numberOfBeverages > 2) {
            BigDecimal discount = grandTotal.multiply(DISCOUNT_RATE);
            grandTotal = grandTotal.subtract(discount);
        }
        return grandTotal;
    }
}

It captures add() and addAll() method calls, forwards them to its superclass and keeps track of the number of the beverages which are added in the numberOfBeverages variable. And it also captures grandTotal() method calls, forwards them to its superclass and applies the 20% discount to the grand total the superclass calculated depending on the numberOfBeverages variable.

It might look reasonable as it reuses the Order class effectively so that it won’t introduce any duplicate code. But this approach can lead to an unforseen issue due to the fact that the CampaignOrder class relies on a hidden behavior of the Order class, which is that the add() method and the addAll() method work independently. Consider that at some point some other programmer has done some quick refactoring in the addAll() method:

class Order {
    ...
    void add(Beverage beverage) {
        subTotal = subTotal.add(beverage.price());
    }

    void addAll(Collection<? extends Beverage> beverages) {
        for (Beverage beverage : beverages)
            // Someone has done refactoring. Original code was:
            // subTotal = subTotal.add(beverage.price());
            // Now:
            add(beverage);
    }
    ...
}

It hasn’t broken anything in terms of the functionality of the Order class but unfortunately it has just broken the CampaignOrder class. Remember the implementation of the CampaignOrder class which captures both of the add() and the addAll() method calls and counts the number of the beverage objects it receives. Due to the fact that now the Order class calls the add() method from the addAll() method, whenever the addAll() method of the CampaignOrder class gets called, the number of the beverage objects gets counted twice in the CampaignOrder class. In other words, now the following test case fails:

@ExtendWith(MockitoExtension.class)
class CampaignOrderTest {

    @Mock
    Beverage coffee, tea;
    CampaignOrder sut = new CampaignOrder();

    @Test
    void addAll() {
        when(coffee.price()).thenReturn(new BigDecimal("2.0"));
        when(tea.price()).thenReturn(new BigDecimal("3.0"));

        sut.addAll(Arrays.asList(coffee, tea));

        // It fails after the refactoring. Now grandTotal() returns 4.4
        // The discount is applied unexpectedly since the logic which counts beverages is broken
        // Now it's counted as 4, which is over the threshold of the discount
        assertThat(sut.grandTotal()).isEqualByComparingTo("5.5");
    }
}

The person who has done this refactoring should not be blamed. In fact this person removed a duplicate piece of code, which is a good thing, and it’s not easy to catch such an error. The real problem here is the wrong use of inheritance, which is writing a subclass that relies on an implementation detail of its super class. That introduces fragility to the codebase. Hence using inheritance this way should be avoided.

And also there can be another problematic case where a new method has been added to the Order class. If the new method can be used for adding a beverage, we need to make sure that the CampaignOrder class captures method calls to the new method, but chances are we would not even notice that there was a subclass which we might have to change.

What could have been done instead of inheritance then? The most obvious approach is using composition instead. Let’s rework the class hierarchy and make it like this:

1d07a6e0 893d 4104 bfdb 177221cd449b

The implementation:

interface Order {
    void add(Beverage beverage);
    void addAll(Collection<? extends Beverage> beverages);
    BigDecimal grandTotal();
}

class RegularOrder implements Order {

    private static final BigDecimal TAX_RATE = new BigDecimal("0.1");
    private BigDecimal subTotal = BigDecimal.ZERO;

    @Override
    public void add(Beverage beverage) {
        subTotal = subTotal.add(beverage.price());
    }

    @Override
    public void addAll(Collection<? extends Beverage> beverages) {
        for (Beverage beverage : beverages)
            subTotal = subTotal.add(beverage.price());
    }

    @Override
    public BigDecimal grandTotal() {
        BigDecimal tax = subTotal.multiply(TAX_RATE);
        return subTotal.add(tax);
    }
}

class CampaignOrder implements Order {

    private static final BigDecimal DISCOUNT_RATE = new BigDecimal("0.2");
    private int numberOfBeverages;

    private final Order delegate;

    CampaignOrder() {
        this(new RegularOrder());
    }

    private CampaignOrder(Order delegate) {
        this.delegate = delegate;
    }

    @Override
    public void add(Beverage beverage) {
        delegate.add(beverage);
        numberOfBeverages++;
    }

    @Override
    public void addAll(Collection<? extends Beverage> beverages) {
        delegate.addAll(beverages);
        numberOfBeverages += beverages.size();
    }

    @Override
    public BigDecimal grandTotal() {
        BigDecimal grandTotal = delegate.grandTotal();
        if (numberOfBeverages > 2) {
            BigDecimal discount = grandTotal.multiply(DISCOUNT_RATE);
            grandTotal = grandTotal.subtract(discount);
        }
        return grandTotal;
    }
}

Now the Order class has become an interface which has 2 implementations. One is the RegularOrder class, which was formerly the Order class, and the other one is the CampaignOrder class. An instance of the CampaignOrder class has a reference to a RegularOrder instance in order to reuse its functionality, but the CampaignOrder class doesn’t have any superclass anymore. With the new design, no refactoring of the RegularCampaign class can break the CampaignOrder class as long as the RegularOrder class keeps the contract of the public methods.

One important difference from the inheritance approach is that now the CampaignOrder class no longer relies on any of the implementation details of the RegularOrder class. What it relies on now is the behavior of the public methods of the RegularOrder class, which are all defined in the Order interface.

The good thing about sticking with this approach is that as long as a class keeps its functionality on the public interface level the same, it can change its internal structure without you worrying about breaking something accidentally. It greatly reduces chances of unforseen breakage. Therefore, it will make your codebase more stable. Also, with having the interface, when a new method has been added to the interface, it will make the compilation of its implementors fail since the implementation is missing. With that, unlike with the inheritance solution, we can notice that we have to add the missing implementation to its implementors immediately.

Inheritance is inflexible

Now let’s think about some details of the Beverage interface in the codebase. It has an implemention class called Coffee. The customer can add a condiment such as milk, whip or sugar into it if they want to. For some reason, the original programmer implemented this requirement using inheritance:

faea3261 015d 43d8 be9a 69c44d88c388
interface Beverage {
    BigDecimal price();
    String description();
}

class Coffee implements Beverage {
    @Override public BigDecimal price() { return new BigDecimal("1.99"); }
    @Override public String description() { return "Coffee"; }
}

class CoffeeWithMilk extends Coffee {
    @Override public BigDecimal price() { return super.price().add(new BigDecimal("0.10")); }
    @Override public String description() { return super.description() + ", Milk"; }
}

class CoffeeWithWhip extends Coffee {
    @Override public BigDecimal price() { return super.price().add(new BigDecimal("0.15")); }
    @Override public String description() { return super.description() + ", Whip"; }
}

class CoffeeWithSugar extends Coffee {
    @Override public BigDecimal price() { super.price().add(new BigDecimal("0.05")); }
    @Override public String description() { return super.description() + ", Sugar"; }
}

Now we’ve got a new requirement to implement, which is that a customer should be able to add multiple condiments into coffee. Let’s see if we can do that with inheritance. It would look like the following:

2d51746f 83fd 43ba b0c5 3628272b7d88

We ended up creating a lot of subclasses for all of the combinations. That will do for the time being but think about the future expansion. We will need to create many subclasses everytime we introduce a new condiment. And what if we want to reuse code which is responsible for a condiment for another beverage class, say, a Tea class? It’s not clear if we can do that in a reasonable way with this approach.

Let’s see if we could do better with composition. It would look like the following:

9b0b3122 c78b 4f45 b358 b30e682519dc

The implementation (the Beverage interface and the Coffee class are the same as the ones we have seen before):

class MilkWrapper implements Beverage {
    private final Beverage delegate;

    MilkWrapper(Beverage delegate) { this.delegate = delegate; }

    @Override public BigDecimal price() { return delegate.price().add(new BigDecimal("0.10")); }
    @Override public String description() { return delegate.description() + ", Milk"; }
}

class WhipWrapper implements Beverage {
    private final Beverage delegate;

    WhipWrapper(Beverage delegate) { this.delegate = delegate; }

    @Override public BigDecimal price() { return delegate.price().add(new BigDecimal("0.15")); }
    @Override public String description() { return delegate.description() + ", Whip"; }
}

class SugarWrapper implements Beverage {
    private final Beverage delegate;

    SugarWrapper(Beverage delegate) { this.delegate = delegate; }

    @Override public BigDecimal price() { return delegate.price().add(new BigDecimal("0.05")); }
    @Override public String description() { return delegate.description() + ", Sugar"; }
}

In the new implementation, the classes responsible for condiments hold a reference to a Beverage object instead of extending the Coffee class. They can still reuse the code of the Coffee class but through the Beverage interface. Instead of creating an instance of a subclass of the Coffee class, you need to provide a Coffee instance to the constructor of one of the wrapper classes. Let’s do it like this:

@Test
void coffeeWithMilk() {
    Beverage coffeeWithMilk = new MilkWrapper(new Coffee());
    assertThat(coffeeWithMilk.description()).isEqualTo("Coffee, Milk");
    assertThat(coffeeWithMilk.price()).isEqualByComparingTo("2.09");
}

@Test
void coffeeWithWhip() {
    Beverage coffeeWithWhip = new WhipWrapper(new Coffee());
    assertThat(coffeeWithWhip.description()).isEqualTo("Coffee, Whip");
    assertThat(coffeeWithWhip.price()).isEqualByComparingTo("2.14");
}

@Test
void coffeeWithSugar() {
    Beverage coffeeWithSugar = new SugarWrapper(new Coffee());
    assertThat(coffeeWithSugar.description()).isEqualTo("Coffee, Sugar");
    assertThat(coffeeWithSugar.price()).isEqualByComparingTo("2.04");
}

Now, let’s see how we can implement the new requirement about multiple condiments with the new design. In fact, no change is needed in the Coffee class and the other classes in the diagram. We can do that like this:

@Test
void coffeeWithMilkAndWhip() {
    Beverage coffee = new Coffee();
    coffee = new MilkWrapper(coffee);
    coffee = new WhipWrapper(coffee);

    assertThat(coffee.description()).isEqualTo("Coffee, Milk, Whip");
    assertThat(coffee.price()).isEqualByComparingTo("2.24");
}

@Test
void coffeeWithMilkAndSugar() {
    Beverage coffee = new Coffee();
    coffee = new MilkWrapper(coffee);
    coffee = new SugarWrapper(coffee);

    assertThat(coffee.description()).isEqualTo("Coffee, Milk, Sugar");
    assertThat(coffee.price()).isEqualByComparingTo("2.14");
}

@Test
void coffeeWithMilkAndWhipAndSugar() {
    Beverage coffee = new Coffee();
    coffee = new MilkWrapper(coffee);
    coffee = new WhipWrapper(coffee);
    coffee = new SugarWrapper(coffee);

    assertThat(coffee.description()).isEqualTo("Coffee, Milk, Whip, Sugar");
    assertThat(coffee.price()).isEqualByComparingTo("2.29");
}

First, we create an instance of the Coffee class and then wrap it with the wrapper classes as needed. This is much more flexible than the old approach which required having subclasses for all of the combinations. We can even combine one particular condiment multiple times, which would have been much harder with the inheritance approach:

@Test
void coffeeWithTripleWhip() {
    Beverage coffee = new Coffee();
    coffee = new WhipWrapper(coffee);
    coffee = new WhipWrapper(coffee);
    coffee = new WhipWrapper(coffee);

    assertThat(coffee.description()).isEqualTo("Coffee, Whip, Whip, Whip");
    assertThat(coffee.price()).isEqualByComparingTo("2.44");
}

This design is also better in terms of maintainability. Introducing a new condiment doesn’t impact any other class in the diagram (i.e. there will be no class explosion). Those wrapper classes are highly reusable because they can be reused for anything which implements the Beverage interface. Also, they don’t depend on anything but the Beverage interface. They solely rely on the public methods in the Beverage interface. There will be no breakage as long as the contract of the Beverage interface stays the same.

Conclusion

We’ve seen how improper use of inheritance can make your code fragile and inflexible. Using inheritance just for code reuse can lead to an unforseen problem in the future. And inheritance is not flexible as you might expect. When you are tempted to use inheritance, I recommend considering if you can do it using composition instead. In my experience, inheritance is not the best option for most of such cases.

I would also like to mention that composition opens up a whole new world of clever design ideas in an object oriented programming language. If you want to learn more about it, I recommend checking out the following books:


Java Generics wildcards


Posted on Friday Jul 17, 2020 at 06:49PM in Technology


This entry is a quick introduction to Java Generics wildcards, which make Java code more flexible and type-safe.

Wildcards with extends

Wildcards with extends provide flexibility to code which gets a value out of a container object. For example, let’s consider the following variable definition:

List<? extends Number> list_extendsNumber;

You can think of it as a List which contains elements whose type is a subtype of Number. For example, we can assign the following instances to the variable:

list_extendsNumber = new ArrayList<Number>();
list_extendsNumber = new ArrayList<Integer>(); // Integer extends Number
list_extendsNumber = new ArrayList<BigDecimal>(); // BigDecimal extends Number

But the following doesn’t compile since neither of them is a subtype of Number:

list_extendsNumber = new ArrayList<String>(); // compilation error; a String is not a Number
list_extendsNumber = new ArrayList<Object>(); // compilation error; Number extends Object but not the other way around

As you can see from the examples above, it’s guaranteed that a List which is assigned to the list_extendsNumber variable contains a Number or a value whose type is a subtype of Number. We can use the variable for getting a value out of it as a Number. For example:

// It's guaranteed that it contains a Number or its subtype
Number firstNumber = list_extendsNumber.get(0);

You can even write some utility method like this:

double avg(List<? extends Number> nums) {
    return nums.stream().mapToDouble(Number::doubleValue).average().orElse(0);
}

The avg() method accepts any List whose type parameter is a subtype of Number. For example, the following code which calls the method works fine:

List<Number> nums = Arrays.asList(1, 0.5d, 3);
assert avg(nums) == 1.5d;

List<Integer> ints = Arrays.asList(1, 2, 3);
assert avg(ints) == 2d;

List<BigDecimal> bds = Arrays.asList(new BigDecimal(1), new BigDecimal(2), new BigDecimal(3));
assert avg(bds) == 2d;

But the following is invalid:

List<String> strs = Arrays.asList("foo", "bar", "baz");
avg(strs) // compilation error; a String is not a Number

List<Object> objs = Arrays.asList("foo", 0.5d, 3);
avg(objs) // compilation error; Number extends Object but not the other way around

What’s good about it? Let’s see what happens if we don’t use the wildcard here. Now the method looks like this:

double avg(List<Number> nums) {
    return nums.stream().mapToDouble(Number::doubleValue).average().orElse(0);
}

Now the method can accept only List<Number> that is much less flexible. The following still works:

List<Number> nums = Arrays.asList(1, 0.5d, 3);
assert avg(nums) == 1.5d; // still fine

But neither of them compiles anymore:

List<Integer> ints = Arrays.asList(1, 2, 3);
assert avg(ints) == 2d; // compilation error

List<BigDecimal> bds = Arrays.asList(new BigDecimal(1), new BigDecimal(2), new BigDecimal(3));
assert avg(bds) == 2d; // compilation error

Which means that when you write code which gets values out of a container object (e.g. List), using wildcards with extends provides more flexibility. In other words, your code (or method) will be able to accept a wider range of parameters if wildcards with extends are used appropriately.

The limitation imposed by the use of wildcards with extends is that you won’t be able to put any value except for null through a variable which uses extends. For example:

List<? extends Number> list_extendsNumber = new ArrayList<Integer>();
list_extendsNumber.add(null); // compiles; null is the only exception
list_extendsNumber.add(1); // compilation error

Why? Remember that we can assign any List whose type parameter is a subtype of Number. For example, you can also assign a List whose type parameter is BigDecimal to the list_extendsNumber variable. In that case adding an Integer to the List should be invalid since an Integer is not a BigDecimal. The compiler prevents it from happening thanks to generics and wildcards. Adding a null is fine since null is not tied to a particular type.

Wildcards with super

While wildcards with extends make code which gets a value more flexible, wildcards with super provide flexibility to code which puts a value into a container object. Let’s consider the following variable definition:

List<? super Integer> list_superInteger;

It means a List which contains elements whose type is a supertype of Integer. For example, we can assign the following instances into the variable:

list_superInteger = new ArrayList<Integer>();
list_superInteger = new ArrayList<Number>(); // Number is a supertype of Integer
list_superInteger = new ArrayList<Object>(); // Object is a supertype of Integer

But the following doesn’t compile:

list_superInteger = new ArrayList<String>(); // compilation error; String is not a supertype of Integer

What we can see from the example above is that it’s guaranteed that the List which is assigned to the list_superInteger variable can accept an Integer. We can use it for putting a value into it. For example:

// It's guaranteed that it can accept an Integer
list_superInteger.put(123);

Or you can write some method with it like this:

void addInts(List<? super Integer> ints) {
    Collections.addAll(ints, 1, 2, 3);
}

The method can accept any of the following:

List<Integer> ints = new ArrayList<>();
addInts(ints);
assert ints.toString().equals("[1, 2, 3]");

List<Number> nums = new ArrayList<>();
addInts(nums);
assert nums.toString().equals("[1, 2, 3]");

List<Object> objs = new ArrayList<>();
addInts(objs);
assert objs.toString().equals("[1, 2, 3]");

But the following doesn’t compile:

List<String> strs = new ArrayList<>();
addInts(strs); // compilation error; List<String> cannot accept an Integer

If we didn’t use the wildcard, the method would be less flexible. Let’s say now we have this without a wildcard:

void addInts(List<Integer> ints) {
    Collections.addAll(ints, 1, 2, 3);
}

The following still compiles:

List<Integer> ints = new ArrayList<>();
addInts(ints);
assert ints.toString().equals("[1, 2, 3]");

But the following does not compile anymore:

List<Number> nums = new ArrayList<>();
addInts(nums); // compilation error

List<Object> objs = new ArrayList<>();
addInts(objs); // compilation error

The limitation imposed by the use of wildcards with super is that you will be able to get a value out of a container object only with the Object type. In other words, if you want to get a value out of the list_superInteger variable, this is the only thing you can do:

List<Integer> ints = new ArrayList<>();
ints.add(123);
List<? super Integer> list_superInteger = ints;

Object head = list_superInteger.get(0); // only Object can be used as the type of head
assert head.equals(123);

The following doesn’t compile:

Integer head = list_superInteger.get(0); // compilation error

Why? Remember that we can also assign a List<Number> or a List<Object> to the list_superInteger variable, which means that the only type that we can safely use to get a value out of it is the Object type.

The Get and Put Principle

As we have seen, appropriate use of wildcards provides more flexibility to your code. To summarize when we should use which, there is a good principle to follow:

“The Get and Put Principle: Use an extends wildcard when you only get values out of a structure, use a super wildcard when you only put values into a structure, and don’t use a wildcard when you both get and put.” - Naftalin, M., Wadler, P. (2007). Java Generics And Collections, O’Reilly. p.19

Functional interfaces exemplify this principle. For example, consider a method which accepts objects that implement functional interfaces as follows:

void myMethod(Supplier<? extends Number> numberSupplier, Consumer<? super String> stringConsumer) {
    Number number = numberSupplier.get();
    String result = "I got a number whose value in double is: " + number.doubleValue();
    stringConsumer.accept(result);
}

Supplier is something which you can apply the get priciple to; you only get values out of it. And Consumer is the same for the put principle; you only put values into it.

myMethod() can accept various types of parameters. The user of the method doesn’t necessarily have to pass a Supplier<Number> and a Consumer<String>. The user can also pass a Supplier<BigDecimal> and a Consumer<Object> as follows, but that’s possible only with the use of the wildcards:

Supplier<BigDecimal> bigDecimalSupplier = () -> new BigDecimal("0.5");
AtomicReference<Object> reference = new AtomicReference<>();
Consumer<Object> objectConsumer = reference::set;

myMethod(bigDecimalSupplier, objectConsumer);

assert reference.get().equals("I got a number whose value in double is: 0.5");

Conclusion

We have seen how we can use wildcards, what the benefits of them are and when to use them. To make your code more flexible and reusable, especially when you write a method or a constructor, it’s good practice to think if you can apply wildcards to code which handles an object that has a type parameter. Remembering the get and put principle will be helpful when you do so.


JUnit and Mockito tips


Posted on Friday Jul 03, 2020 at 06:40PM in Technology


In this entry I’ll share some tips about JUnit and Mockito for making unit tests better.

Mockito annotations

Mockito has some annotations that can be used for reducing redundancy of tests:

  • @Mock

  • @InjectMocks

  • @Captor

Before looking into the usage of those annotations, let’s assume we have the following production code which consists of 2 classes.

The first one is called MailServer, which has a method called send() that sends an SMTP message which this object receives as the parameter of the method. Note that the MailServer class most probably needs to be mocked out when you want to write a unit test for a class which uses the MailServer class because it really opens a TCP connection to an SMTP server, which is not a preferable thing for unit tests.

class MailServer {
    void send(String smtpMessage) throws IOException {
        // Opens a connection to an SMTP server, sends the SMTP message
    }
}

The other class is called Messenger, which depends on the MailServer class. This class requires an instance of the MailServer class in its constructor. This class has a method called sendMail(), which has 3 parameters. The responsibility of this method is first constructing an SMTP message based on those 3 parameters and then asking the MailServer object to send the SMTP message. It also does quick error handling which translates IOException into an unchecked one with embedding the content.

class Messenger {

    private final MailServer mailServer;

    Messenger(MailServer mailServer) {
        this.mailServer = mailServer;
    }

    void sendMail(String from, String to, String body) {
        String smtpMessage = String.join("\n", "From: " + from, "To: " + to, "", body);
        try {
            mailServer.send(smtpMessage);
        } catch (IOException e) {
            throw new UncheckedIOException("Error! smtpMessage=" + smtpMessage, e);
        }
    }
}

Let’s try writing a unit test for the Messenger class. But we don’t want to use the real MailServer class because it really tries to open a connection to an SMTP server. It will make testing harder because in order to test with the real MailServer class, we really need an SMTP server which is up and running. Let’s avoid doing that and try using a mocked version of a MailServer instance for the testing here.

A happy path test case would look like the following:

class MessengerPlainTest {

    MailServer mailServer;
    Messenger sut;

    @BeforeEach
    void setUp() {
        mailServer = Mockito.mock(MailServer.class);
        sut = new Messenger(mailServer);
    }

    @Test
    @DisplayName("Messenger constructs the SMTP message and feeds MailServer")
    void test() throws IOException {
        String expected = "From: joe@example.com\n"
                + "To: jane@example.com\n\n"
                + "Hello!";

        sut.sendMail("joe@example.com", "jane@example.com", "Hello!");

        Mockito.verify(mailServer).send(expected);
    }
}

In the setUp() method, a mock MailServer object is created and injected into the constructor of the Messenger class. And in the test() method, first we create the expected SMTP message which the Messenger class has to create, then we call the sendMail() method and finally we verify that the send() method of the mock MailServer object has been called with the expected SMTP message.

With annotations, the test above can be written as follows:

@ExtendWith(MockitoExtension.class)
class MessengerTest {

    @Mock
    MailServer mailServer;
    @InjectMocks
    Messenger sut;

    @Test
    @DisplayName("Messenger constructs the SMTP message and feeds MailServer")
    void test() throws IOException {
        String expected = "From: joe@example.com\n"
                + "To: jane@example.com\n\n"
                + "Hello!";

        sut.sendMail("joe@example.com", "jane@example.com", "Hello!");

        Mockito.verify(mailServer).send(expected);
    }
}

First we annotate the test class with @ExtendWith(MockitoExtension.class) (Note that it’s a JUnit5 specific annotation, so for JUnit4 tests we need something different). Having the test class annotated with that one, when there is a field annotated with @Mock in the test class, Mockito will automatically create a mock for the field and inject it. And when there is a field annotated with @InjectMocks, Mockito will automatically create a real instance of the declared type and inject the mocks that are created by the @Mock annotation.

This is especially beneficial when many mock objects are needed because it reduces the amount of repetitive mock() method calls and also removes the need for creating the object which gets tested and injecting the mocks into the object.

And also it provides a clean way to create a mock instance of a class which has a parameterized type. When we create a mock instance of the Consumer class, a straightforward way would be the following:

Consumer<String> consumer = Mockito.mock(Consumer.class);

The problem here is that it produces an unchecked assignment warning. Your IDE will complain about it and you will get this warning when the code compiles with -Xlint:unchecked :

Warning:(35, 49) java: unchecked conversion
  required: java.util.function.Consumer<java.lang.String>
  found:    java.util.function.Consumer

With the @Mock annotation, we can get rid of the warning:

@ExtendWith(MockitoExtension.class)
class MyTest {

    @Mock
    Consumer<String> consumer;
...

There is another useful annotation called @Captor. Let’s see the following test case:

@ExtendWith(MockitoExtension.class)
class MessengerCaptorTest {

    @Mock
    MailServer mailServer;
    @InjectMocks
    Messenger sut;

    @Captor
    ArgumentCaptor<String> captor;

    @Test
    @DisplayName("Messenger constructs the SMTP message and feeds MailServer")
    void test() throws IOException {
        sut.sendMail("joe@example.com", "jane@example.com", "Hello!");

        Mockito.verify(mailServer).send(captor.capture());
        String capturedValue = captor.getValue();
        assertTrue(capturedValue.endsWith("Hello!"));
    }
}

The @Captor annotation creates an object called ArgumentCaptor which captures a method parameter of a method call of a mock object. In order to capture a parameter with an ArgumentCaptor, first we need to call the capture() method in a method call chain of the Mockito.verify() method. Then we can get the captured value with the getValue() method and we can do any assertion against it. It’s especially useful in a situation where checking the equality is not sufficient and a complex verification is needed.

AssertJ

AssertJ is an assertion library for unit tests written in Java. It provides better readability and richer assertions than its older equivalents like the one shipped with JUnit. Let’s see some example code from the official website:

// entry point for all assertThat methods and utility methods (e.g. entry)
import static org.assertj.core.api.Assertions.*;

// basic assertions
assertThat(frodo.getName()).isEqualTo("Frodo");
assertThat(frodo).isNotEqualTo(sauron);

// chaining string specific assertions
assertThat(frodo.getName()).startsWith("Fro")
                           .endsWith("do")
                           .isEqualToIgnoringCase("frodo");

// collection specific assertions (there are plenty more)
// in the examples below fellowshipOfTheRing is a List<TolkienCharacter>
assertThat(fellowshipOfTheRing).hasSize(9)
                               .contains(frodo, sam)
                               .doesNotContain(sauron);

A unique feature of AssertJ is that all of the assertions here begin with the method assertThat() which receives the parameter that gets asserted. After that we specify the conditions the parameter needs to fulfill. An advantage of this approach is that we can specify multiple conditions with method call chain. It’s more readable and less verbose than the old way where repetitive assertTrue() or assertEquals() calls are involved. It also provides rich assertions for widely used classes like List, Set or Map.

Another useful feature of AssertJ is for verifying an unhappy path where an Exception is involved. Let’s remember the production code we used in the Mockito annotation section and consider a situation where the MailServer cannot connect to the SMTP server. Due to that, the send() method throws IOException. In this situation, the Messenger class is expected to catch the IOException and translate it into UncheckedIOException with the SMTP message embedded. A unit test for this can be written as follows with AssertJ:

@ExtendWith(MockitoExtension.class)
class MessengerUnhappyTest {

    @Mock
    MailServer mailServer;
    @InjectMocks
    Messenger sut;

    @Test
    @DisplayName("Messenger throws UncheckedIOException with the SMTP message when MailServer has thrown IOException")
    void test() throws IOException {
        doThrow(new IOException("The server is down")).when(mailServer).send(any());
        String expectedMessage = "From: joe@example.com\n"
                + "To: jane@example.com\n\n"
                + "Hello!";

        assertThatThrownBy(() -> sut.sendMail("joe@example.com", "jane@example.com", "Hello!"))
                .isInstanceOf(UncheckedIOException.class)
                .hasMessage("Error! smtpMessage=%s", expectedMessage)
                .hasCauseInstanceOf(IOException.class);
   }
}

First we make the mock MailServer instance throw IOException when its send() method is called. After that we pass a lambda expression which calls the sendMail() method to the assertThatThrownBy() method of AssertJ. After that we can do various assertions. What we are checking here is that the sendMail() method throws UncheckedIOException with the SMTP message embedded and it also contains a parent Exception whose class is IOException.

Conclusion

We’ve discussed some tips about Mockito and the basic uses of AssertJ for test cases that are written in JUnit. Both Mockito and AssertJ have extensive documents and rich functionality which greatly helps writing unit tests. I highly recommend checking the references below:

The pieces of code which are used in this entry can be found on GitHub: https://github.com/nuzayats/junittips


JPA Builder パターン


Posted on Sunday Dec 04, 2016 at 12:00AM in Technology


このエントリは Java EE Advent Calendar 2016 の4日目の記事です.


JPA のおかげで,多数のカラムや複雑なリレーションを持つテーブルへのレコード生成は,プレーンな JDBC を使っていた時代に比べると,たいへん楽になりました.しかし,いぜん頭を悩ませる局面もあります.例えば,以下の図のようなスキーマを考えてみてください:

829fc6f6 cccb 44c2 816a b7f397e83309

このスキーマ中の Employee テーブルへレコードを生成するコードを考えてみてください.以下のようになると思います:

public class EmployeeService {

    private final EntityManager em;

    EmployeeService(final EntityManager em) {
        this.em = em;
    }

    public long create(long deptId,
                       String name,
                       boolean temporary,
                       Set<Long> projectIds,
                       Set<String> phoneNumbers) {

        // instantiating and setting attributes of employee
        final Employee employee = new Employee();
        employee.setName(name);
        employee.setTemporary(temporary);
        employee.setProjects(new HashSet<>());
        employee.setPhones(new HashSet<>());

        // making a relation between employee and dept
        final Dept dept = em.find(Dept.class, deptId);
        employee.setDept(dept);
        em.persist(employee);
        dept.getEmployees().add(employee);

        // making relations between employee and projects
        for (final Long projectId : projectIds) {
            final Project project = em.find(Project.class, projectId);
            project.getEmployees().add(employee);
            employee.getProjects().add(project);
        }

        // creating phones
        for (final String phoneNumber : phoneNumbers) {
            final Phone phone = new Phone();
            phone.setNumber(phoneNumber);
            phone.setEmployee(employee);
            em.persist(phone);
            employee.getPhones().add(phone);
        }

        em.flush(); // making sure a generated id is present

        return employee.getId();
    }
}

いま書いたメソッド create() を呼び出すコードは,以下のようになります:

final Set<Long> projectIds = new HashSet<>();
Collections.addAll(projectIds, project1Id, project2Id);
final Set<String> phoneNumbers = new HashSet<>();
Collections.addAll(phoneNumbers, "000-0000-0001", "000-0000-0002", "000-0000-0003");

final long savedEmployeeId = service.create(
        engineeringDeptId,
        "Jane Doe",
        true,
        projectIds,
        phoneNumbers);

悪くはありません.しかし,もっと複雑なリレーションや省略可能なカラムが多数存在するケースを考えてみてください.それらに対応するメソッドの引数も多くなるのにしたがって,省略可能な引数に対応するためのオーバーロードや null の引数が並ぶメソッド呼び出しも増殖していき,だんだんメンテナンスが大変になっていきます.

このようなケースでは,私が個人的に「JPA Builder パターン」と呼んでいる書き方がおすすめです.以下に示すような非 static のネストされた Builder クラスと,そのインスタンスを生成するためのメソッドを,前述の EmployeeService クラスに対して追加します:

...

public Builder builder(long deptId, String name) {
    return new Builder(deptId, name);
}

public final class Builder { // non-static
    private final long deptId;
    private final String name;
    private boolean temporary;
    private Set<Long> projectIds = new HashSet<>();
    private Set<String> phoneNumbers = new HashSet<>();

    private Builder(final long deptId, final String name) {
        this.deptId = deptId;
        this.name = name;
    }

    public Builder temporary(boolean temporary) {
        this.temporary = temporary;
        return this;
    }

    public Builder projectIds(Long... ids) {
        Collections.addAll(projectIds, ids);
        return this;
    }

    public Builder phoneNumbers(String... numbers) {
        Collections.addAll(phoneNumbers, numbers);
        return this;
    }

    public long build() {
        // In reality, passing "this" instead of actual values (deptId, name, ...) is recommended
        return EmployeeService.this.create(deptId, name, temporary, projectIds, phoneNumbers);
    }
}

これを呼び出すコードは,以下のようになります:

final long savedEmployeeId = service.builder(engineeringDeptId, "Jane Doe")
        .temporary(true)
        .projectIds(project1Id, project2Id)
        .phoneNumbers("000-0000-0001", "000-0000-0002", "000-0000-0003")
        .build();

今回の例のようにリレーションや省略可能なカラムの数がさほど多くない場合,あまりメリットがないように見えるかもしれませんが,現実には,もっと多い数になることは珍しくありません.そのようなケースでは,このパターンを使うことで保守性・可読性を維持・向上させることができます.

このエントリで使用したクラスとテストを含むサンプルの一式は以下にありますので,実際に動かしてみたい方はチェックしてみてください.EclipseLink と Hibernate での動作を確認しています.DB のセットアップなどは必要なく,単に "mvn test" を叩くとインメモリの Apache Derby 上でテストが走ります:

宣伝: 求人のご案内

現在,私の勤めている (株) L is B では,エンジニアを募集しています.主に "direct" という企業向けメッセンジャーの開発と運用を行っている会社です.

残念ながら,今のところ GlassFish や WildFly のようなフルの Java EE コンテナは使われていないのですが,Java EE の構成要素,例えば JPA や JAX-RS などはヘビーに使われています.「Java EE を使って自社サービス開発したい!」という方,ぜひ以下をチェックしてみてください:


Jersey 1.x ExceptionMapper examples


Posted on Saturday Oct 29, 2016 at 12:42PM in Technology


CAUTION: this posting is about Jersey 1.x which is obsoleted. If you use more modern JAX-RS implementation such as Jersey 2.x or above, please check if there are any better approaches.

JAX-RS (Jersey) provides a mechanism called ExceptionMapper which is an universal way to map an exception that thrown by a JAX-RS implementation itself or application code, to any HTTP response. In this posting, I’ll introduce some basic but useful usages of it that I have found.

ExceptionMapper for RuntimeException

When your resource method throw an Exception, say, an unintentional NullPointerException which caused by a bug or something, typically this produces a 500 Error page which created by your application container. You can catch, log those exceptions and produce a customer-friendly response with an ExceptionMapper which is something like following:

@Provider
public class RuntimeExceptionMapper implements ExceptionMapper<RuntimeException> {

    private static final Logger LOGGER = Logger.getLogger(RuntimeExceptionMapper.class.getName());

    @Override
    public Response toResponse(final RuntimeException e) {
        // taken from http://stackoverflow.com/questions/13716793/jersey-how-to-register-a-exceptionmapper-that-omits-some-subclasses
        if (e instanceof WebApplicationException) {
            return ((WebApplicationException) e).getResponse();
        }

        LOGGER.log(Level.WARNING, "RuntimeException occurred", e);

        return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                .entity("Sorry, something went wrong")
                .build();
    }
}

ExceptionMapper for NotFoundException

When your app receive a request which has no corresponding resource method, typically this produces a 404 Error page created by your container as well as an uncaught Exception. You can handle this situation with an ExceptionMapper as follows:

@Provider
public class NotFoundExceptionMapper implements ExceptionMapper<NotFoundException> {

    private static final Logger LOGGER = Logger.getLogger(NotFoundExceptionMapper.class.getName());

    @Override
    public Response toResponse(final NotFoundException e) {
        LOGGER.log(Level.FINE, "NotFoundException occurred", e);

        return Response.status(Response.Status.NOT_FOUND)
                .entity("Check the destination path of your request - we have no API here")
                .build();
    }
}

ExceptionMapper for ParamExceptionMapper

Let’s say you have a value class which is something like following:

public class EmployeeId {

    private final long value;

    public EmployeeId(final long value) {
        if (value < 1) {
            throw new IllegalArgumentException("EmployeeId must be larger than zero");
        }

        this.value = value;
    }

    public EmployeeId(final String value) {
        this(Long.parseLong(value));
    }

    // getter and toString omitted
}

And you have a resource method which receives an EmployeeId as follows:

@Path("myresource")
public class MyResource {

    @GET
    @Path("emp")
    @Produces(MediaType.TEXT_PLAIN)
    public String emp(@QueryParam("id") EmployeeId id) {
        ...
    }
}

When the resource method receives a valid id, say 123, Jersey automatically constructs an EmployeeId instance and passes it to the application code. That’s fine, but consider if a malicious user has sent an invalid value, say -1. Typically this produces an error page which created by your container as well. You may want to return a more informational response with HTTP status code 400 with an ExceptionMapper which is something like:

@Provider
public class ParamExceptionMapper implements ExceptionMapper<ParamException> {

    private static final Logger LOGGER = Logger.getLogger(ParamExceptionMapper.class.getName());

    @Override
    public Response toResponse(final ParamException e) {
        LOGGER.log(Level.FINE, "ParamException occurred", e);

        final StringBuilder sb = new StringBuilder("Your parameter '" + e.getParameterName() + "' is invalid");

        final Throwable cause = e.getCause();
        if (cause instanceof IllegalArgumentException) {
            final String message = cause.getMessage();
            if (message != null && !message.isEmpty()) {
                sb.append(": ").append(message);
            }
        }

        return Response.status(Response.Status.BAD_REQUEST)
                .entity(sb.toString())
                .build();
    }
}

Conclusion

ExceptionMapper helps making error responses of your REST APIs more helpful. And it reduces repetitive exception handling code in your resource classes that tend to be tons of boilarplate.

You can obtain complete code based on Jersey 1.x and testcases that powered by Arquillian, Embedded Tomcat and Apache HttpClient, from my GitHub repository.