AssertJ, Java, JUnit, Maven, Mockito, Spring Framework

I against U

As we know now, that we should test each and every part of code, it is time to cover our application with tests. We can distinguish two main types of automatic tests:

  • unit
  • integration

Today, I’m going to show you how to set up environment for testing purpose using IntelliJ, maven, jUnit, AssertJ, Mockito and Spring Framework.

You can modify application we made for purpose of this post or clone final sample directly from github.

przechwytywanie

We will need to keep without any changes configuration class, that we made recently, named Config and bean Person, but this time we will remove boilerplate code using library I have written about here.

@Component
@Data
class Person {
    private final String name = "Seba";
}

As you should remember, @Data annotation will take care of toString() method, which was the only one existing in last project within this class.

Let’s add some dependencies to pom.xml, to cover our needs:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>4.3.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>1.2.0</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.12</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <version>1.10.19</version>
</dependency>

All of these dependencies will provide us what we really need to do, but let’s take a little break here to understand the difference between topic’s test types.

When you unit test some class, you cover only what is provided by this specific class. All other classes, systems or resources should be treated as constant values and you have to prepare mock-ups for them. For preparing mocks, we will use great library – Mockito, which is brilliant, when it comes to unit testing.

On the other hand, when you have to write integration tests, you will have to set up whole or some part of environment. It means, that you will test what should happen in real life.

As you can see, the difference between unit and integration testing is like between small box and huge box. I am purposefully not telling you what type of box is it, because I will bring up this subject in one of future posts. For our example let make this box black, so you know what you put to it and what you expect, but you don’t care what happens in the middle.

Now, when you understand the difference, we will write two simple tests, one for each case from subject.

Our unit test will use Mockito to mock bean Person, jUnit to mark methods properly with annotations and AssertJ to write assertion in human readable form instead of Java’s keyword, which is not as friendly as mentioned library:

assert result != null;

Our test class should look like this:

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class SampleUnitTest {

 @Mock
 private Person person;

 @Before
 public void setUp(){
 when(person.getName()).thenReturn("Mockito");
 }

 @Test
 public void testOnSuccess() {
 assertThat(person.getName()).isNotEqualTo("Seba");
 }

}

It is essential to use @RunWith annotation, to init mocks without calling this command in the initial method:

MockitoAnnotations.initMocks(this);

And when we are talking about init method in test, it can be marked two ways:

  • @Before – when we want method to be called before each method annotated with @Test
  • @BeforeClass – when we want static method to be called at the very begging of initializing test class, but only once before all tests in test class

Our method setUp() has only one line, which is in very readable form. It means, that when we call our Person mock’s getName(), we always want to “Mockito” to be returned.

The last part of test class is test called testOnSuccess(), which is marked with self-explanatory annotation. It also has one line, which means: assert that person.getName() is not equal to “Seba”. Easy as pie. We did not set up Spring Context for that test. We faked, that we have person initialized using Mockito and made sure, that it’s name is not the one, that is constant in bean, when Spring Context is up. If you don’t remember the line I’m talking about, here it is:

private final String name = "Seba";

When class Person is initialized, it has hardcoded name “Seba”, so we proved, that mocking works as expected.


For the second test we will set up Spring Context, so we need to use @ContextConfiguration annotation above test class as here:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
public class SampleIntegrationTest {

    @Autowired
    private Person person;

    @Test
    public void testOnSuccess() {
        assertThat(person.getName()).isEqualTo("Seba");
    }

    @Test(expected = AssertionError.class)
    public void testOnFail() {
        assertThat(person.getName()).isEqualTo("John");
    }
}

We need to tell runner class basing on which configuration we will work during this test. In this case our runner will SpringJUnit4ClassRunner instead of MockitoJUnitRunner, because now we don’t need to mock anything, but if we would like to either way, we could use initMocks() method.

Thanks to setting up Spring Context based on Config class, we can now use @Autowire annotation, to tell Spring Context, that it has to inject bean under person field. And all of that happens without calling constructor, because Spring will do that instead of us.

Our first test checks if Spring Context was set up properly, so the hardcoded field name is initialized properly with “Seba” String, while the second test should fail. We are curious if Spring Context is not returning String values which match to each and every other value, that we pass in assertion. As we can see, we added parameter to our annotation. It is pretty simple also and means, that we expect this assertion inside to fail and throw AssertionError.


To run tests click with right mouse button on package with them and choose option Run ‘Tests’ in ‘com.tddsample’. When your tests will be finished, you should see something like I pasted below:

przechwytywanie

All tests passed. We are happy developers with test coverage higher than 0%.

Last, but very important thing: NEVER TEST GETTERS AND SETTERS UNTIL THEY ONLY RETURN AND SET VALUE WITHOUT OTHER COMMANDS! It was only for simplifying examples.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s