Spring #PropertyValue annotation is not working in Unit Test - java

I have email.properties file under /src/main/resources/ and also in /src/test/resources/ folder.
I am trying to read the properties using #PropertyValue annotation.
I have registered the Bean in my SpringConfig.java file.
Inside SpringConfig.java :
public class SpringConfig extends WebMvcConfigurerAdapter {
#Bean
public static PropertySourcesPlaceholderConfigurer propertyConfigInDev() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Inside EmailConfig.java :
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
#Configuration
#PropertySource("classpath:/src/main/resources/email.properties")
public class EmailConfig {
#Value("${smtp_userName}")
private String smtp_userName;
#Value("${forgotPasswordTemplate}")
private String forgotPasswordTemplate;
#Value("${forgotPasswordSubject}")
private String forgotPasswordSubject;
// corresponding getter, setters and constructors ()
}
I wrote a unit test for the above piece which is not working!
Inside my EmailConfigTest.java :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.testng.Assert;
import org.testng.annotations.Test;
import com.time.dal.config.EmailConfig;
public class EmailConfigTest {
#Autowired
EmailConfig emailConfig;
#Value("${smtp_userName}")
private String smtp_userName;
#Value("${forgotPasswordTemplate}")
private String forgotPasswordTemplate;
#Value("${forgotPasswordSubject}")
private String forgotPasswordSubject;
#Test
public void testEmailConfig(){
System.out.println("SMTP User Name is "+smtp_userName);
Assert.assertNotNull(smtp_userName);
}
Here's my error :
SMTP User Name is null FAILED: testEmailConfig
java.lang.AssertionError: expected object to not be null at
com.time.dal.utils.EmailConfigTest.testEmailConfig(EmailConfigTest.java:31)

Related

Springboot adding a "_class" field in POST Request

I am new to SpringBoot and I am trying to connect my SpringBoot App to MongoDB. The GET Request is working completely fine but the POST Request is adding a "_class" field in the data which I don't want. I did some searching and found that I have to add a #Configuration class to solve this issue but when I added the #Configuration class, I am getting the following error :
Field mongoDbFactory in com.example.demo.configuration.MongoConfig required a bean of type 'org.springframework.data.mongodb.MongoDbFactory' that could not be found.
My Confuguration class code is as follows :-
MongoConfig.java :-
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
#Configuration
public class MongoConfig {
#Autowired
private MongoDbFactory mongoDbFactory;
#Autowired
private MongoMappingContext mongoMappingContext;
#Bean
public MappingMongoConverter mappingMongoConverter() {
DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory);
MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver,
mongoMappingContext);
converter.setTypeMapper(new DefaultMongoTypeMapper(null));
return converter;
}
}
Controller.java :-
import com.example.demo.model.Todo;
import com.example.demo.services.TodoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
public class Controller {
#Autowired
private TodoService todoService;
#GetMapping("/")
public List<Todo> getTodos() {
return todoService.getTodos();
}
#PostMapping("/")
public Todo addTodo(#RequestBody Todo todo) {
return todoService.addTodo(todo);
}
}
TodoService.java :-
import com.example.demo.model.Todo;
import java.util.List;
public interface TodoService {
public List<Todo> getTodos();
public Todo addTodo(Todo todo);
}
TodoServiceImplementation.java :-
import com.example.demo.model.Todo;
import com.example.demo.repository.TodoRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class TodoServiceImplementation implements TodoService{
#Autowired
private TodoRepository todoRepository;
#Override
public List<Todo> getTodos() {
return todoRepository.findAll();
}
#Override
public Todo addTodo(Todo todo) {
return todoRepository.save(todo);
}
}
It is asking me to do the following action :-
Consider defining a bean of type 'org.springframework.data.mongodb.MongoDbFactory' in your configuration.

Consider defining a bean of type 'com.example.transaction.manager.properties.TransacationManagerProperties' in your configuration

TransactionManagerApplication
package com.example.transaction.manager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Profile;
import com.comvia.transaction.manager.properties.TransacationManagerProperties;
#SpringBootApplication
#ComponentScan("com.example")
public class TransactionManagerApplication {
#Autowired
private TransacationManagerProperties yamlFooProperties;
public static void main(String[] args) {
SpringApplication.run(TransactionManagerApplication.class, args);
TransactionManagerApplication manager = new TransactionManagerApplication();
manager.print();
}
public void print() {
System.out.println("yamlFooProperties :: "+yamlFooProperties.getPassword());
}
}
TransacationManagerProperties
package com.example.transaction.manager.properties;
import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import com.comvia.transaction.manager.properties.factory.YamlPropertySourceFactory;
import lombok.Data;
#Configuration
#PropertySource(value = "transaction_manager.yml", factory = YamlPropertySourceFactory.class)
#Profile("development")
#Data
public class TransacationManagerProperties {
#Value("${db.userName}")
private String userName;
#Value("${db.password}")
private String password;
#Value("${list}")
private List<String> list;
}
Getting error while starting application :
***************************
APPLICATION FAILED TO START
***************************
Description:
Field yamlFooProperties in com.comvia.transaction.manager.TransactionManagerApplication required a bean of type 'com.example.transaction.manager.properties.TransacationManagerProperties' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.example.transaction.manager.properties.TransacationManagerProperties' in your configuration.
Remove autowiring of beans from the class where you start the application because the beans are not registered unless this line of code SpringApplication.run(<SomeClass>.class, args) runs.
Modify in this way given below :
Updated TransactionManagerApplication class :
#SpringBootApplication
public class TransactionManagerApplication {
public static void main(String[] args) {
SpringApplication.run(TransactionManagerApplication.class, args);
}
}
Create a sample class implementing CommandLineRunner (which is an interface and telling spring that this bean should run when present in SpringApplication. In simple words, this will execute after SpringApplication.run(<SomeClass>.class, args) is executed.
#Component
public class TransactionManagerRunner implements CommandLineRunner {
#Autowired
private TransacationManagerProperties yamlFooProperties;
#Override
public void run(String... args) throws Exception {
System.out.println("yamlFooProperties :: "+yamlFooProperties.getPassword());
}
}

Spring boot environment variable are not reflecting properly

I am working on spring boot application where I want to completely externalize my environment variables dynamically by config server.
So below is the code I have written.
Application.java
package com.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
#Configuration
#SpringBootApplication
#EnableAutoConfiguration
#ComponentScan("com.myPackage, com.util")
#PropertySource("classpath:application.properties")
public class Application extends SpringBootServletInitializer {
static final Logger logger = LoggerFactory.getLogger(Application.class);
public static ApplicationContext ctx;
public static void main(String[] args) throws Exception {
logger.info("Application starting....");
ctx = SpringApplication.run(Application.class, args);
logger.info("Application started successfully....");
}
#Bean
public static PropertySourcesPlaceholderConfigurer
propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
application.properties
server.port=${server.port}
ENDPOINT_SHAN=${name.mya}
Config Server:
APPLICATION_NAME=myapp
server.port=8081
name.mya=myName
To Read Properties
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import com.apptium.Application;
#Component("configurationProperties")
public class ConfigurationProperties {
private static Environment prop;
public static String getConfigValue(String key) {
String value = null;
if (prop == null) {
prop = Application.ctx.getBean(Environment.class);
}
if (prop.getProperty(key) != null) {
value = prop.getProperty(key).trim();
}
if (value == null && System.getenv(key) !=null) {
value = System.getenv(key).trim();
}
return value;
}
}
so, when I try to get the property ENDPOINT_SHAN, it is returning
ENDPOINT_SHAN==${name.mya} but it needs to return ENDPOINT_SHAN==myName
And also am wondering how the property for server.port is taken correctly.
Anyways, I would like to know, how to get an actual property for ENDPOINT_SHAN.
You said that name.mya is defined in a "Config Server" but your code doesn't show any connection being established to this server. You need to read it from the server before ${name.mya} becomes resolvable.

Primitive type dependency injection in spring boot

Can you please provide me with an example of primitive type dependency injection in spring boot. I have tried once but TestConfiguration which is my custom bean definition class does not detect or does not recognize by spring boot application.
here is my code,
//Engine class
package com.test2.projectTest;
import org.springframework.stereotype.Component;
#Component
public class Engine {
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
//Test Configuration
package com.test2.projectTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class TestConfiguration {
#Bean("engine")
public Engine engine(){
Engine engine = new Engine();
engine.setMsg("Message is injected");
return engine;
}
}
//spring main application
package com.test2.projectTest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
public class ProjectTestApplication {
public static void main(String[] args) {
SpringApplication.run(ProjectTestApplication.class, args);
}
}
//JUnit Test
package com.test2.projectTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.ApplicationContext;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest
public class ProjectTestApplicationTests {
#Test
public void contextLoads() {
ApplicationContext apc = new
AnnotationConfigApplicationContext(TestConfiguration.class);
Engine e = (Engine) apc.getBean("engine");
e.getMsg();
}
}
// Output - org.springframework.beans.factory.NoSuchBeanDefinitionException:
No bean named 'engine' available
Please suggest any solution to above issue
Add #componentscan annotation in main class and provide engine class package and it should work

Spring with JUnit Testing and Dependency Injection does not work

I try to use Springs own Dependency Injection in a Junit test case:
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.binarisinformatik.api.AppConfig;
import org.binarisinformatik.satzrechner.SatzRechner;
import org.junit.Before;
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;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=AppConfig.class)
//#SpringApplicationConfiguration(classes = {AppConfig.class})
public class SatzRechnerTest {
#Autowired
private SatzRechner satzRechner; //SUT
#Before
public void setUp() {
// AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SatzRechnerTest.class);
//satzRechner=context.getBean(SatzRechner.class);
}
#Test
public void addiere_satz_4komma6_zu_zahlwert_10() {
assertThat("Addition von \"4,6\" ergibt nicht 10!",
satzRechner.summe("4,6"), is(equalTo(10)));
}
Im testing a class names SatzRechner in which Spring should also autowire some variables. Here is my Class under test:
#Component
public class SatzRechner {
#Autowired //#Inject
private Rechner taschenRechner;
#Autowired
private Zahlenfabrik zahlenfabrik;
public Integer summe(String zeichenSatz) {
return taschenRechner.summe(zahlenfabrik.erzeugeZahlen(zeichenSatz));
}
}
And AppConfig.class which is using as Configurationfile looks like that:
#Configuration
#ComponentScan(value={"org.binarisinformatik"})
public class AppConfig {
}
What is here the problem?
If you want to use a Spring configuration class, this one must have beans definitions. Please find an example below :
Test class:
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import org.binarisinformatik.api.AppConfig;
import org.binarisinformatik.satzrechner.SatzRechner;
import org.junit.Before;
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;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=AppConfig.class)
public class SatzRechnerTest {
#Autowired
private SatzRechner satzRechner;
#Test
public void addiere_satz_4komma6_zu_zahlwert_10() {
assertThat("Addition von \"4,6\" ergibt nicht 10!",
satzRechner.summe("4,6"), is(equalTo(10)));
}
}
Configuration class :
You have to declare #Bean annotated methods. These beans are managed by Spring container.
#Configuration
public class AppConfig {
// Beans present here will be injected into the SatzRechnerTest class.
#Bean
public SatzRechner satzRechner() {
return new SatzRechner();
}
#Bean
public Rechner taschenRechner() {
return new TaschenRechner();
}
#Bean
public Zahlenfabrik zahlenfabrik() {
return new Zahlenfabrik();
}
}
Note : I let you properly handle returned types here and beans parameters (if present in your context).
There are two things you have to ensure before you run the test case successfully:
1) Classes SatzRechner, Rechner & Zahlenfabrik should be under "org.binarisinformatik" package
2) Classes Rechner & Zahlenfabrik should also be annotated with #Component as SatzRechner.

Categories