SpringBoot unit test autowired field NullPointerException

Introduction

This post would demo how to solve the NullPointerException when using springboot unit testing.

Environments

  • SpringBoot 1.5.9
  • Java 1.8

Class under test

This is the class under test, it’s just a simple class.

// An interface which return the length of a string
public interface StringLengther {
    int getLength(String s);
}

@Component
public class LambdaCUT {
    public int s1(StringLengther stringLengther,String s) {
        return stringLengther.getLength(s);
    }
}

As you can see, this class uses the StringLengther to get the string length.

The unit test code

public class TestLambdas {
    @Autowired
    private LambdaCUT lambdaCUT;

    @Test
    public void test3() {
        assertEquals(lambdaCUT.s1((String s)->s.length(),"comeon"),6);
    }
}

As you can see, we use a @Test annotation to test the lambdaCUT’s s1 method, And the lambdaCUT instance is @Autowired by the spring container.

Problem occurring

Now run the unit test, you can see the result:

java.lang.NullPointerException
	at TestLambdas.test3(TestLambdas.java:45)

Problem debugging

We can debug the problem by adding a breakpoint at the line of the problem, and rerun it,we would got this:

image-title-here

we can see that the root cause is the lambdaCUT property is null, but we @Autowired it! The autowire process must be disabled by some reason.

Problem solving

After debugging, we found that the root cause is the @Autowire not working, and we found that the UnitTest is a common junit test case, and is not a springboot testcase, so there is no spring container for it. This is the root cause, And then, we change the code like this:

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestLambdas {
    @Autowired
    private LambdaCUT lambdaCUT;

    @Test
    public void test3() {
        assertEquals(lambdaCUT.s1((String s)->s.length(),"comeon"),6);
    }
}

rerun the test, and we got this:

 .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.9.RELEASE)
2018-04-16 21:19:25.414  INFO 38582 --- [           main] java8.learn.lambda.TestLambdas           : Starting TestLambdas on -Pro.local with PID 38582 (started by  in /Users/xxx/JavaProjects/xxx_tests/test-java8)
2018-04-16 21:19:25.415 DEBUG 38582 --- [           main] java8.learn.lambda.TestLambdas           : Running with Spring Boot v1.5.9.RELEASE, Spring v4.3.13.RELEASE
2018-04-16 21:19:25.416  INFO 38582 --- [           main] java8.learn.lambda.TestLambdas           : No active profile set, falling back to default profiles: default
2018-04-16 21:19:25.956  INFO 38582 --- [           main] java8.learn.lambda.TestLambdas           : Started TestLambdas in 1.196 seconds (JVM running for 2.167)
Process finished with exit code 0

You can find detail documents about the springboot and unit testing here: