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:
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: