Testing using spring boot throws null pointer exception - java

I am new to spring boot and i am trying to test a very simple class. But when i run the testMe() below I get exception below
java.lang.NullPointerException
at MyTest.testMe(MyTest.java:25)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
My understanding is when the context is loaded all the beans are initialized and object HelloWorld is created and are autowired in MyTest call. But helloWorld object is null at line helloWorld.printHelloWorld();
I need assistance here to understand what is missing.
#RunWith(MockitoJUnitRunner.class)
#SpringBootTest(classes = {AppConfigTest.class})
public class MyTest {
#Mock
#Autowired
private Message myMessage;
#Autowired
private HelloWorld helloWorld;
#Test
public void testMe(){
helloWorld.printHelloWorld();
}
}
#Configuration
public class AppConfigTest {
#Bean
public HelloWorld helloWorld() {
return new HelloWorldImpl();
}
#Bean
public Message getMessage(){
return new Message("Hello");
}
}
public interface HelloWorld {
void printHelloWorld();
}
public class HelloWorldImpl implements HelloWorld {
#Autowired
Message myMessage;
#Override
public void printHelloWorld() {
System.out.println("Hello : " + myMessage.msg);
}
}
public class Message {
String msg;
Message(String message){
this.msg = message;
}
}

You're running your tests with a runner that's not Spring-aware, so no wiring is happening. Look at the Spring Boot testing documentation, all their examples use #RunWith(SpringRunner.class). To mock a bean, annotate it with #MockBean, not #Mock. Make sure that the spring-boot-starter-test is included in your POM.

Related

How to initialise Spring AnnotationConfigApplicationContext inside #BeforeTest in Testng?

I have a testng+spring suite with parallel option set to Tests. I would like to have each <test> have it's own ApplicationContext. So each <test> thread will have their own set of beans. I am able to initialise the ApplicationContext but the beans are not getting autowired and I am getting nullpointer exception when I am trying to access the bean. Please find my code below,
AppTest.class
#ComponentScan(basePackages = "org.comp.automation")
public class AppTest extends AbstractTestNGSpringContextTests{
#BeforeTest
public void intialise() throws Exception{
ApplicationContext context = new AnnotationConfigApplicationContext(BeanTwo.class);
}
#Autowired
public CommonBean commonBean;
#Autowired
public BeanTwo beanTwo;
#Parameters(value={"param"})
#Test
public void shouldAnswerWithTrue(String param) {
System.out.println(commonBean.STRING_CHECK);
commonBean.createCommonBeanObject(param);
System.out.println("Checking the bean values now...");
assertTrue( true );
}
}
CommonBean.class
#Component
public class CommonBean {
public String commonBeanValue;
public String STRING_CHECK = "Hello!!";
public void createCommonBeanObject(String param){
commonBeanValue = param;
}
public void printParamValue(){
System.out.println(commonBeanValue);
}
}
BeanTwo.class
#Component
public class BeanTwo{
public void printBeanTwo(){
System.out.println("Bean Two!!");
}
}
Can someone help me with this and point me in the right direction?

MockBean doesn't work in Spring boot integration test

I have Spring Integration test where I'm trying to Mock some of my Beans. For some reason although I Mocked them they are NULL. Here is code snippet:
The Bean which I want to Mock
#Component
public class MockWS {
public String callSoapClient() throws JAXBException{
return "CallSoapCl";
}
}
The class where the Bean is used
public class SmDpES2PortImpl implements ES2SmDp {
#Autowired
private MockWS mock;
#Override
public void es2DownloadProfile(ES2DownloadProfileRequest parameters) {
try {
LOG.info("\n\n\n TEST BEAN: " + mock.callSoapClient() + "\n\n");
}
}
}
Spring boot integration test where the Bean has been mocked
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ES2SmDpApplicationTests {
#MockBean(name="mockWS")
MockWS mockService;
#Test
public void test1Es2DownloadProfile_Sucess() throws MalformedURLException, JAXBException, SOAPException {
when(mockService.callSoapClient()).thenReturn("CallMockCLient");
}
}
Output from the build execution: TEST BEAN: null
In my case the following combination of annotations worked:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { ControllerThatIAmTesting.class })
#AutoConfigureMockMvc(addFilters = false) // if using MockMvc object
But I had to declare explicitly both Autowired objects that I use in the ControllerThatIAmTesting in the test class with #MockBean annotation - otherwise Spring would complain that it cannot find suitable implementation - incidentally both my interfaces and their implementations are in the same corresponding packages
Also, using #WebMvcTest instead of #SpringBootTest (other suggest it as more specific scenario) resulted in Spring failing to find and initialize some other #Autowired dependencies from my #Configuration classes.
Related posts post1 post2 post3
You should mock an interface, not a class. Also, SmDpES2PortImpl must be a Spring bean. Try the following:
Interface:
public interface IMockWS {
public String callSoapClient() throws JAXBException;
}
Component class:
#Component
public class MockWS implements IMockWS {
#Override
public String callSoapClient() throws JAXBException{
return "CallSoapCl";
}
}
Service class:
#Service //Also #Component is a good alternative
public class SmDpES2PortImpl implements ES2SmDp {
#Autowired
private IMockWS mock; //Notice that you are wiring an interface
#Override
public void es2DownloadProfile(ES2DownloadProfileRequest parameters) {
try {
LOG.info("\n\n\n TEST BEAN: " + mock.callSoapClient() + "\n\n");
}
}
}
Test class:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ES2SmDpApplicationTests {
#MockBean
IMockWS mockService; //Again, you are mocking the interface, not the implementing class
#Test
public void test1Es2DownloadProfile_Sucess() throws MalformedURLException, JAXBException, SOAPException {
when(mockService.callSoapClient()).thenReturn("CallMockCLient");
}
}

How to read spring boot property file in service class method called by unit test

I have spring boot application. I want to write some unit test for methods in service class.
I can load Environment variable and get properties in unit test class but can't do it in service class. Environment in service class is always null when reaching it from unit tests. It work when reaching it from application.
SomethingServiceTest.java
#RunWith(SpringRunner.class)
#DataJpaTest
#TestPropertySource(value = "/application.properties")
public class SomethingServiceTest {
private ISomethingService m_SomethingService;
#PostConstruct
public void setup() {
m_SomethingService = new SomethingService();
m_SomethingService.setSomethingRepository(somethingRepository);
// somethingRepository is mocked class, probably not important
}
#Test
public void test_somethingMethod() {
System.out.println(env.getProperty("some.property"));
//env here is full and i get wanted property
m_uploadService.doSomething();
}
ISomethingService.java
public interface ISomethingService {
doSomething();
}
SomethingService.java
#Service
public class SomethingService implements ISomethingService {
#Value("${some.property}")
private String someProperty;
private ISomethingRepository somethingRepository;
#Autowired
public ISomethingRepository getSomethingRepository() {
return somethingRepository;
}
public void setSomethingRepository(ISomethingRepository p_somethingRepository) {
somethingRepository = p_somethingRepository;
}
#Autowired
private Environment env;
#Override
#Transactional
public String doSomething(){
System.out.println(env.getProperty("some.property"));
//env is null here
return someProperty;
}
}

NullPointerException: Junit Spring annotation configuration

I am learning Spring framework and using this reference,
I have a UkranianSongs class
import javax.annotation.Nonnull;
public class UkrainianSongs implements CompactDisk{
#Override
#Nonnull
public String getTitle(){
return "Ukranian Songs";
}
#Override
#Nonnull
public String getArtist(){
return "Skriabin";
}
}
I am creating a bean in CDPlayerConfig class
#Configuration
#ComponentScan
public class CDPlayerConfig {
#Bean
public CompactDisk anUkranianDisk(){
return new UkrainianSongs();
}
}
And I am autowiring compact disk class in another class
#Component
public class CompactDiskBox {
#Autowired
public CompactDisk anUkrainianDisk;
}
I wrote a JUnit test where I am trying to assert anUkranianDisk bean was initialized correctly and is not null
#RunWith(JUnit4.class)
#ContextConfiguration(classes = CDPlayerConfig.class)
public class CompactDiskBoxTest {
#Autowired(required = true)
public CompactDiskBox compactDiskBox;
#Test
public void testUkranianDisk(){
assertNotNull(compactDiskBox.anUkrainianDisk);
}
}
This throws a NullPointerException as compactDiskBox is null which means it couldn't initialize the bean right. Am I missing something here?
In order to be able to use dependency injection in your unit/integration tests, you have to set up the Spring TestContext Framework. In order to do this you should run your tests with SpringJUnit4ClassRunner.class or SpringRunner.class. SpringRunner.class is just an alias for SpringJUnit4ClassRunner.class.

Spring Aspect Advice #Test methods

I have a test class :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = IntegrationTestConfig.class)
#Transactional
#Component
public class AppTest {
#Autowired
private SimpleService simpleService;
#Test
public void test() {
simpleService.test();
}
}
I want make an aspect in order to monitor test method invocation
#Aspect
public class TestAspect {
#Pointcut("#annotation(org.junit.Test)")
public void pointcut() {
}
#After("pointcut()")
public void monitor() {
System.out.println("*** AFTER TEST ***");
}
}
Config :
#Configuration
#ImportResource("classpath:context.xml")
public class IntegrationTestConfig {
#Bean
public TestAspect testAspect() {
return new TestAspect();
}
}
But my monitor method has not been invoked, what's wrong? Generally - can I advice test methods?? I want to know which test method has been invoked.
JUnit itself has Rules that can be used for this.

Categories

Resources