spring messagesource while testing - java

i have message source defined in my java config as :
#Bean(name = "messageSource")
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasenames(
"/i18n/ir/kia/industry/webapp/entity",
"/i18n/ir/kia/industry/webapp/formErrors",
"/i18n/ir/kia/industry/webapp/frontend",
"/i18n/ir/kia/industry/webapp/frontendPages");
return messageSource;
}
it works fine when using site and messages are displayed correctly, but when trying to write spring test with :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {TestContext.class, SpringMVC.class})
#WebAppConfiguration
public abstract class AbstractTestClass {
protected MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
#Before
public void setUp() throws Exception {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
}
and a test class that simply extends it, i get error Can't find bundle for base name /i18n/ir/kia/industry/webapp/entity.
it works fine when starting tomcat and using message source in jsp files, but no luck when testing it. i have tried moving i18n folder under WEB-INF but it did not help it neither.
the target folder looks like this and please do not tell me add i18n folder to target resources ...

i managed to solve the problem by removing the message source base names using spring profile feature. i changed the message source part to :
#Bean(name = "messageSource")
#Profile(value = {"dev","prod"})
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasenames(
"/i18n/ir/kia/industry/webapp/entity",
"/i18n/ir/kia/industry/webapp/formErrors",
"/i18n/ir/kia/industry/webapp/frontend",
"/i18n/ir/kia/industry/webapp/frontendPages");
messageSource.setCacheSeconds(5);
return messageSource;
}
#Bean(name = "messageSource")
#Profile("test")
public MessageSource testMessageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
return messageSource;
}
and add test profile to my test unit with
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {TestContext.class, SpringMVC.class})
#WebAppConfiguration
#ActiveProfiles("test")
public abstract class AbstractTestClass {
that when i was able to run my tests, but that is a way around for solving problem. i'm still confused for what was the reason of error in the first place.
it that some sort of bug? or i'm doing something wrong?

Related

Spring Web: ControllerAdvice

I have the simple class to catch some exceptions like this:
#ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler(RuntimeException.class)
public ResponseEntity<Object> handleRuntimeException(Exception ex) {
log.debug("[RuntimeException throw]");
return new ResponseEntity<>(responseMessage, HttpStatus.OK);
}
}
Then I can throw new RuntimeException and can see the output log in console.
It well done works but I have to move the RestResponseEntityExceptionHandler.class to another project as a lib and add this like a maven dependency in pom.xml.
Also in the main project added ControllerAdvice which extends moved:
#ControllerAdvice
public class ResponseEntityExceptionHandler extends RestResponseEntityExceptionHandler { }
After that it does not work. I have the next exception:
org.springframework.context.NoSuchMessageException: No message found under code 'description' for locale 'ru_RU'.
When RestResponseEntityExceptionHandler was in the main project, I had the next bean definition:
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource
= new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
and in the 'resource' folder I had messager_ru.properties file. I moved the messageSource bean config and properties file too.
Perhaps the point is that the project that I moved all this to is a library (no main function)?

No message available MVC

I have a message bundle under my resources in src/main the resources with messages are named messages_en_US.properties i.e. and I am getting the message to my JSP.
#Component
public class Messages {
private MessageSource messageSource;
#Autowired
public Messages(MessageSource messageSource) {
this.messageSource = messageSource;
}
private MessageSourceAccessor accessor;
#PostConstruct
private void init() {
accessor = new MessageSourceAccessor(messageSource);
}
public String get(String code) {
return accessor.getMessage(code);
}
}
When I used the code above without any beans I had an exception that informed me there is no code for a message. So I added a BeanHelper class as below.
#Configuration
#ComponentScan("com")
public class BeansHelper {
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
return messageSource;
}
}
When now I am trying to go on localhost:8000/ I am getting an 404 that says there is no message available. What is wrong in this code? My messages are under src/main in the resources. But the JSP of course are in WEB-INF/views/ any ideas guys how to solve the problem? I correctly added message properties file to my Local.

Spring boot junit test failed loading application context

When i run junit test on class MailServiceTest it works fine, but when I'm trying to do mvn build -B it fails.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = InstaticketapiApplication.class)
public class MailServiceTest {
#Autowired
private ApplicationProperties applicationProperties;
#Autowired
private MessageSource messageSource;
#Autowired
private SpringTemplateEngine springTemplateEngine;
#Spy
private JavaMailSenderImpl javaMailSender;
#Captor
private ArgumentCaptor messageCaptor;
#Autowired
private MailService mailService;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
doNothing().when(javaMailSender).send(any(MimeMessage.class));
mailService = new MailService();
mailService.setApplicationProperties(applicationProperties);
mailService.setJavaMailSender(javaMailSender);
mailService.setMessageSource(messageSource);
mailService.setTemplateEngine(springTemplateEngine);
}
#Test
public void testSendEmail() throws Exception {
mailService.sendEmail("nemanja#test.com", "testSubject", "testCont", false, false);
verify(javaMailSender).send((MimeMessage) messageCaptor.capture());
MimeMessage message = (MimeMessage) messageCaptor.getValue();
assertThat(message.getSubject()).isEqualTo("testSubject");
assertThat(message.getContent().toString()).isEqualTo("testCont");
assertThat(message.getAllRecipients()[0].toString()).isEqualTo("nemanja#test.com");
assertThat(message.getFrom()[0].toString()).isEqualTo("InstaTicket");
assertThat(message.getContent().getClass()).isEqualTo(String.class);
assertThat(message.getDataHandler().getContentType()).isEqualTo("text/plain; charset=UTF-8");
}
Full code could be find here https://github.com/sansajn5/ISA-InstaTicketAPI , I'm using yaml for properites.Also I used structure as Jhipster generated project
Normally you wouldn't load the Spring context file and then instantiate a component in a test via mailService = new MailService();
If you are writing a unit tests, don't load the Spring context file and mock all the dependencies of the component you intent to test.
If you are writing integration tests, don't mock dependencies, let the framework to load the context and wire dependencies.
The problem is this line: mailService = new MailService(). Remove it.
In simple language let the #Autowired annotation take care of instantiation in jUnit using SpringBoot.

How can I mock db connection in Spring Boot for testing purpose?

Situation:
I am using Spring Cloud with Spring Boot in a microservice, that microservice is loading a DB config information to configure a connection.
I created a test to get the rest interfaces using Swagger for documentation.
I want to disable the loading of DB configuration because is not necessary.
Here is the code:
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {Application.class, Swagger2MarkupTest.class}, loader = SpringApplicationContextLoader.class)
#ActiveProfiles("test")
public class Swagger2MarkupTest {
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#Autowired
protected Environment env;
#Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
#Test
public void convertSwaggerToAsciiDoc() throws Exception {
this.mockMvc.perform(get("/v2/api-docs").accept(MediaType.APPLICATION_JSON))
.andDo(Swagger2MarkupResultHandler.outputDirectory("target/docs/asciidoc/generated")
.withExamples("target/docs/asciidoc/generated/exampless").build())
.andExpect(status().isOk());
}
}
How can I run the test without loading the database configuration?
Is this possible?
There is an option to fake Spring bean with just plain Spring features. You need to use #Primary, #Profile and #ActiveProfiles annotations for it.
I wrote a blog post on the topic.
You can use in memory DB (e.g. H2) to replace real data source. Something like this:
#Configuration
public class TestingDataSourceConfig {
#Bean
#Primary
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScript("schema.sql")
.addScripts("user_data.sql", "country_data.sql")
.build();
}
}

Spring 4 Framework Internationalization not identify message from resource properties file with thymeleaf

Using new spring version, with thymeleaf, is not my specialty, with gradle,
I try a lot ways change position files and configurations of basename and still receiving ??welcome.message_**?? on template result.
#EnableAutoConfiguration
#Configuration
#ComponentScan
public class Application {
[...]
#Bean
public ReloadableResourceBundleMessageSource resourceBundleMessageSource(){
ReloadableResourceBundleMessageSource messageSource=new ReloadableResourceBundleMessageSource();
String[] resources= {"/WEB-INF/locale/messages", "WEB-INF/locale/messages", "locale/messages", "i18n", "locale"};
messageSource.setBasenames(resources);
messageSource.setFallbackToSystemLocale(true);
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public LocaleChangeInterceptor localeChangeInterceptor(){
LocaleChangeInterceptor localeChangeInterceptor=new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
return localeChangeInterceptor;
}
#Bean
public SessionLocaleResolver sessionLocaleResolver(){
SessionLocaleResolver localeResolver=new SessionLocaleResolver();
localeResolver.setDefaultLocale(new Locale("pt","BR"));
return localeResolver;
}
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
Template:
<h1 th:text="#{welcome.message}">Welcome!</h1>
have 2 properties on src/java/webapp/WEB-INF/local/messages.properties and src/java/webapp/WEB-INF/local/messages_pt_BR.properties
github project: https://github.com/brunoguerra/springtutorial/tree/master/web-scure-jpa
Thanks for any ideia
After walk around I found samples from spring-projects on github. The solution is very simple, just define public MessageSource messageSource() on your MVC configurer instead public ReloadableResourceBundleMessageSource resourceBundleMessageSource() on application configurer.
#Configuration
#EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
[...]
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("/WEB-INF/messages/messages");
return messageSource;
}
The bean name should be messageSource
We can do it either
#Bean(name ="messageSource")
public MessageSource anyName() {}
Or
public MessageSource messageSource() {}

Categories