How do you choose several common assertion styles in Java

Time:2020-11-26

In daily work, whether you write unit test or use TDD programming method for development, you will encounter assertions. The common assertion styles include assert and BDD. How do you choose these common assertion styles?

01 assert style

JUnit provides such assertion style as:


  void should_be_unlocked_when_insert_coin_given_a_entrance_machine_with_locked_state() {
    EntranceMachine entranceMachine = new EntranceMachine(EntranceMachineState.LOCKED);

    String result = entranceMachine.execute(Action.INSERT_COIN);

    assertEquals("opened", result);
    assertEquals(EntranceMachineState, entranceMachineState.UNLOCKED);
  }

Both hamcrest and assertj provide assertions in the style of assertthat(), such as:

Assertion syntax of assertthat() provided by assertj


  void should_be_unlocked_when_insert_coin_given_a_entrance_machine_with_locked_state() {
    EntranceMachine entranceMachine = new EntranceMachine(EntranceMachineState.LOCKED);

    String result = entranceMachine.execute(Action.INSERT_COIN);

    assertThat(result).isEqualsTo("opened");
    assertThat(EntranceMachineState).isEqualsTo(entranceMachineState.UNLOCKED);
  }

Assertthat() assertion syntax provided by hamcrest


  void should_be_unlocked_when_insert_coin_given_a_entrance_machine_with_locked_state() {
    EntranceMachine entranceMachine = new EntranceMachine(EntranceMachineState.LOCKED);

    String result = entranceMachine.execute(Action.INSERT_COIN);

    assertThat(result, is("opened"));
    assertThat(EntranceMachineState, is(entranceMachineState.UNLOCKED));
  }

Compared with the above three assertion syntax, because the scenario is simple, the results are not very different. For me, I prefer to use the assertion style provided by assertj. We often encounter problems with JUnit expected before assertions. After all, it is not necessary to find out the problem of whether or not to only find a clear style of assertj in comparison with that of assertj in the daily work.

If TDD is used in daily work, and the scenario is appropriate (for example, the above example), the difference between hamcreate and assertj is not great. JUnit 5 provides the assertion of hamcreate by default, and there is no need to introduce additional dependencies.

02 BDD style

More and more attention has been paid to the readability of code. The readability of test code is also important. In order to make the structure of test code clear and make it easy to read and understand the test context quickly when the business logic changes, many development teams have agreed on the BDD style to organize the test code. There are two parts of the contract: the Convention of test method name and the Convention of test code paragraph.

For example, the previous example:


void should_be_unlocked_when_insert_coin_given_a_entrance_machine_with_locked_state() {
   ...
  }

Although the method name is very long, through the method name, we can quickly know which tests are in the test class. Through the method name, we can clearly know the context of the current test, what is being tested, and what the expected results are. After all, the time of reading and modifying code may be 10:1 or even 20:1. So the team agreed that the BDD style organization would benefit a lot from subsequent code changes.

When it comes to bringing specific test code, the team found that organizing the code in the BDD style benefited a lot. For example:


  void should_be_unlocked_when_insert_coin_given_a_entrance_machine_with_locked_state() {
    EntranceMachine entranceMachine = new EntranceMachine(EntranceMachineState.LOCKED);

    String result = entranceMachine.execute(Action.INSERT_COIN);

    assertThat(result).isEqualsTo("opened");
    assertThat(EntranceMachineState).isEqualsTo(entranceMachineState.UNLOCKED);
  }

We can clearly know which line of code is describing the context, which lines of code are describing the test intent, and which lines are describing the test result verification.

The BDD style can help the team maintain the test code more clearly. Assertj provides BDD style assertions. Use the then () syntax. For example:


@Test
  void should_be_unlocked_when_insert_coin_given_a_entrance_machine_with_locked_state() {
    EntranceMachine entranceMachine = new EntranceMachine(EntranceMachineState.LOCKED);

    String result = entranceMachine.execute(Action.INSERT_COIN);

    then(result).isEqualsTo("opened");
    then(EntranceMachineState).isEqualsTo(entranceMachineState.UNLOCKED);
  }

The assertion does not change much. But when you really read it carefully, you will find that using then () is still a little simple.

Our commonly used mock tool, mockito, also provides BDD style assertions: then(), should(), and().


import static org.mockito.BDDMockito.then;
import static org.assertj.core.api.BDDAssertions.and;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;

@SuppressWarnings("static-access")
@Test
public void bdd_assertions_with_bdd_mockito() {
 Person person = mock(Person.class)
 person.ride(bike);

 person.ride(bike);

 then(person).should(times(2)).ride(bike);
 and.then(person.hasBike()).isTrue();
}

Therefore, in daily development, I will first choose then (), and then I will choose assertthat().

In addition to the above two assertion styles, stream assertion makes the code clearer and the assertion repeats less

When we need to test multiple test points for a result, if we organize the same context once for each test point, there is too much duplicate code. The value brought about is just a little difference, so in terms of testing strength, we can dynamically adjust it in the development project according to experience.

As an example, when we need to verify the results of a list returned by a query method, we need to verify not only the number of elements in the list, but also whether the elements are in the expected order. Then streaming writing will reduce some of the repeated assertion code.


then(users).hasSize(3)
      .containsExactlyInAnyOrder(
        firstUser,
        secondUser,
        thirdUser);

The above is the assertion technique often used in daily work. How do you choose it? That style doesn’t matter. It just works?

reference resources

Hamcrest

AssertJ

The above is the whole content of this article, I hope to help you in your study, and I hope you can support developeppaer more.