How to get my test working with JUnit5 using SpringExtension? - java

I'm trying to get my test using JUnit5, but am getting a NullPointerException on the auto-wired restTemplate bean.
TestConfig:
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
#Configuration
public class TestConfig {
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
Working using JUnit4 classes:
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.apache.commons.lang3.math.NumberUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import lombok.extern.log4j.Log4j2;
#RunWith(SpringRunner.class)
#SpringBootTest
#ContextConfiguration(classes = {TestConfig.class, RestTemplateAutoConfiguration.class})
#Log4j2
public class Test {
#Value("${service.url.base}/security-marking/count")
private String countUrl;
#Autowired
private RestTemplate restTemplate;
#Test
public void testCount() throws Exception {
LOG.info(countUrl);
ResponseEntity<String> response = restTemplate.getForEntity(countUrl, String.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertTrue(NumberUtils.isDigits(response.getBody()));
assertTrue(NumberUtils.toInt(response.getBody()) >= 0);
}
}
Fails with NullPointerException when calling restTemplate.getForEntity(...):
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.apache.commons.lang3.math.NumberUtils;
import org.junit.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.*.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.web.client.RestTemplate;
import lombok.extern.log4j.Log4j2;
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = {TestConfig.class, RestTemplate.class})
#Log4j2
#AutoConfigurationPackage
public class Test {
#Value("${service.url.base}/bob/count")
private String countUrl;
#Autowired
private RestTemplate restTemplate;
#Test
public void testCount() throws Exception {
LOG.info(countUrl);
ResponseEntity<String> response = restTemplate.getForEntity(countUrl, String.class);
assertEquals(HttpStatus.OK, response.getStatusCode());
assertTrue(NumberUtils.isDigits(response.getBody()));
assertTrue(NumberUtils.toInt(response.getBody()) >= 0);
}
}
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<!-- Your own application should inherit from spring-boot-starter-parent -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath />
</parent>
<artifactId>api-integration</artifactId>
<groupId>group.id</groupId>
<name>Integration Test</name>
<description>Integration Test</description>
<version>0.0.1-SNAPSHOT</version>
<properties>
<main.basedir>${basedir}/..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<!-- HELPERS -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Stack Trace:
java.lang.NullPointerException
at Test.testCount(Test.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

Misantorp was correct.
I had to fix the import path for #Test and remove the restTemplate bean definition method from TestConfig.java.
Fix #1 - Fix Import and use RestTemplateAutoConfiguration:
Change import org.junit.Test; to import org.junit.jupiter.api.Test;
and
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = {TestConfig.class, RestTemplateAutoConfiguration.class})
#Log4j2
Fix #2 - Fix Import and use remove the bean from RestConfig:
Change import org.junit.Test; to import org.junit.jupiter.api.Test;
and
#ExtendWith(SpringExtension.class)
#SpringBootTest(classes = {TestConfig.class, RestTemplate.class})
#Log4j2
public class SecurityMarkingsTest {
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
#Configuration
public class TestConfig {
// #Bean
// public RestTemplate restTemplate(RestTemplateBuilder builder) {
// return builder.build();
// }
}

Related

Unable to use swagger in spring application

I have followed the steps mentioned in https://www.baeldung.com/swagger-2-documentation-for-spring-rest-api to add swagger to a plain spring application -
I added the maven dependencies -
<!-- for swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!-- end of swagger dependency -->
I created 2 classes for configuration -
package com.luv2code.springdemo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
#Configuration
#EnableSwagger2
#EnableWebMvc
public class SpringFoxConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}
and
package com.luv2code.springdemo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
#EnableWebMvc
public class SpringFoxUIConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
but It is not working
I had this problem too. Add a / at the end of your url.
Like this:
http://localhost:8080/spring-rest-demo/swagger-ui/

Could not autowire. No beans of 'JobRepositoryTestUtils' type found. With SpringBatchTest Annotation added

I am working on a Spring Batch unit testing using the #SpringBatchTest annotation which is supposed to automatically add the beans for JobLauncherTestUtils and JobRepositoryTestUtils.
Here's the Job configuration class:
#Configuration
#EnableBatchProcessing
public class JobConfiguration {
#Bean
public Job getJob(JobBuilderFactory jobBuilderFactory,
#Qualifier("flow_master") Flow flowMaster) {
return jobBuilderFactory.get("job")
.incrementer(new RunIdIncrementer())
.start(flowMaster)
.build().build();
}
}
Here's the Test Class:
#ExtendWith(SpringExtension.class)
#SpringBatchTest
#ContextConfiguration(classes = JobConfiguration.class)
public class SpringBatchTest {
#Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
#Before
public void clearJobExecutions() {
this.jobRepositoryTestUtils.removeJobExecutions();
}
#Test
public void testMyJob() throws Exception {
JobParameters jobParameters = this.jobLauncherTestUtils.getUniqueJobParameters();
JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);
Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
}
Problem:
I am getting the error messages:
Could not autowire. No beans of 'JobLauncherTestUtils' type found.
I have cloned some repo examples which are supposed to work but I am getting the same error for all of them.
Am I missing something?
You did not share your imports but you are probably mixing imports between junit4 and junit5. I'm not able to reproduce your error. Here is a complete example:
The job configuration class:
package com.example.demo;
import javax.sql.DataSource;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
#Configuration
#EnableBatchProcessing
public class MyJobConfig {
#Bean
public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) {
return jobs.get("job")
.start(steps.get("step")
.tasklet((contribution, chunkContext) -> {
System.out.println("Hello world!");
return RepeatStatus.FINISHED;
}).build())
.build();
}
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("/org/springframework/batch/core/schema-h2.sql")
.build();
}
public static void main(String[] args) throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(MyJobConfig.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
jobLauncher.run(job, new JobParameters());
}
}
The test class:
package com.example.demo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.batch.test.JobRepositoryTestUtils;
import org.springframework.batch.test.context.SpringBatchTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
#SpringBatchTest
#ContextConfiguration(classes = MyJobConfig.class)
class MyJobConfigTest {
#Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
#Autowired
private JobRepositoryTestUtils jobRepositoryTestUtils;
#BeforeEach
public void clearJobExecutions() {
this.jobRepositoryTestUtils.removeJobExecutions();
}
#Test
public void testMyJob() throws Exception {
// given
JobParameters jobParameters = this.jobLauncherTestUtils.getUniqueJobParameters();
// when
JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);
// then
Assertions.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
}
and the pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>so67767525</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>so67767525</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<!-- While this has "boot" in the name, it does not bring any Spring Boot feature. -->
<!-- It is used to manage Spring projects dependencies that are known to work correctly together -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
The test runs successfully without the error you mentioned.

Getting Error for MockMvc perform() Methods

I am creating a Spring MVC Controller test. Compiler is showing errors for methods shown below in bold. Am I missing some library or something in my code? Any suggestions?
I am using following dependencies:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MockMvcBuilder;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import com.zerosolutions.view.form.LoginCredentials;
#RunWith(value=SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration("classpath:dispatcher-servlet.xml")
public class TestingFrontController {
#Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setUp(){
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
#Test
public void getLoginSignupPage() throws Exception{
this.mockMvc.perform(**get**("/"))
.andExpect(status().isOk())
.andExpect(forwardedUrl("login"))
.andExpect(model().attribute("loginCred", **any**(LoginCredentials.class)));
}
}
add following to import these methods
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;

Spring Boot basic Cacheing is Not working for me

I am trying to do a simple cache of data but everytime I test it. It never seems to cache the data.
package app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
#EnableAutoConfiguration
#SpringBootApplication
#EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("getUserInfo");
}
}
package app.cache;
import app.repo.User.User;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
#Service
public class UserService {
private User userInfo;
#CacheEvict("getUserInfo")
public void setUserInfo(User userInfo) {
this.userInfo = userInfo;
}
#Cacheable("getUserInfo")
public User getUserInfo() {
return userInfo;
}
}
package app.controllers;
import app.cache.UserService;
import app.repo.User.Player;
import app.repo.User.User;
import app.repo.User.UserRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
#RestController
public class UserController {
#Autowired
private UserService userCache;
#RequestMapping("/test-user-cache")
#ResponseBody
public User testUserCache() {
if(userCache.getUserInfo() != null) {
return userCache.getUserInfo();
}
User user = new User("joejoe","wordpass");
user.setId(44444444);
userCache.setUserInfo(user);
return userCache.getUserInfo();
}
}
Dependencies
...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.apache.directory.server</groupId>
<artifactId>apacheds-server-jndi</artifactId>
<version>1.5.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies>
...
It doesnt seem to save the data when I try to save it. And when I do a request again, no data is never cached.
You get that behavior because the cache works. The data is saved, but null is already cached: if(userCache.getUserInfo()
In order to clear the cache when you set the value you can annotate the setUserInfo Method with #CacheEvict(cacheNames="books", allEntries=true).

Spring Mail Generating Null Pointer exception

I'm trying to configure mail in Spring and keep getting a null pointer exception. My suspicion is that it can't find the "mailSender" bean but I could be way off. My configuration is as follows:
web.xml
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>logVerbosityLevel</param-name>
<param-value>ERROR</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<beans:bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<beans:property name="host" value="mail.company.com"/>
</beans:bean>
</beans:beans>
SendMailTest.java
package company.test;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.activation.CommandMap;
import javax.activation.MailcapCommandMap;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mock.web.MockServletContext;
import company.AppListener;
public class SendMailTest {
private static final Logger logger = AppListener.getLogger();
#Mock
private ServletContextEvent mockServletContextEvent;
private final Map<String, Object> map = new HashMap<String, Object>();
#Mock
private ServletContext mockServletContext;
#Before
public void setUp() {
System.setProperty("java.net.preferIPv4Stack" , "true");
initMocks(this);
map.clear();
when(mockServletContextEvent.getServletContext()).thenReturn(mockServletContext);
Mockito.doAnswer(new Answer<Object>() {
public Object answer(final InvocationOnMock invocation)
throws Throwable {
final String key = (String) invocation.getArguments()[0];
final Object value = invocation.getArguments()[1];
return map.put(key, value);
}
}).when(mockServletContext).setAttribute(Mockito.anyString(), Mockito.anyObject());
Mockito.doAnswer(new Answer<Object>() {
public Object answer(final InvocationOnMock invocation)
throws Throwable {
final Object value = invocation.getArguments()[0];
return map.remove(value);
}
}).when(mockServletContext).removeAttribute(Mockito.anyString());
}
#Autowired
private MailSender mailSender;
#Test
public void testSendSimpleEmaill() {
SimpleMailMessage message = new SimpleMailMessage();
String name = "John Doe";
message.setFrom("john.doe#company.com");
message.setTo("jane.doe#company2.com");
message.setSubject("Test Email from Spring");
message.setText("Will email ever work?");
try {
mailSender.send(message);
}
catch (Exception e) {
e.printStackTrace();
System.err.println(e.getMessage());
}
}
}
Stack Trace
java.lang.NullPointerException
at company.test.SendMailTest.testSendSimpleEmaill(SendMailTest.java:85)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
null
When you're running the test with JUnit, Spring isn't loaded at all, so the autowired fields aren't being set. To run spring in a test, look into the SpringJUnit4ClassRunner.
You can also create your own instance of JavaMailSenderImpl within the setUp method and assign it to mailSender
yu need to put the configurations in your test class, also you whould like to copy your context file to the root of your test class (just file resolution, when the spring runners starts needs to load your context file)..your test class should look like this...
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 org.springframework.test.context.web.WebAppConfiguration;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "applicationContext.xml" })
#WebAppConfiguration
public class FacadeTest {
private String phoneNumber = "111111115";
#Autowired
private BussinesDelegate bussinesDelegate;
#Test
public void runTest(){
this.fullTest(phoneNumber, "aaaaa");
}
public void fullTest(String phoneNumber, String answer){
try {
bmoaBussinesDelegate.processMessage("127.0.0.1", phoneNumber, "camicase" + System.currentTimeMillis());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
and dont forget to check your dependencies!
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- Testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.8.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
The cool thing about spring, its that its IOC container can probide the same behavior as a full Java EE compliant server without needing a server, and basically what the runner does is to load the context manually, the same way you could do ir in a standole app with spring ;)

Categories