JUnit application.properties always returning null - java

I am trying to write unit tests for #Service annotated class. I have application.properties file set and a class to access the values.
#Component
#ConfigurationProperties
#PropertySource("classpath:application.properties")
public class ApplicationProperties {
private String first_name;
private String last_name;
private String base_url;
public String getFirst_name() {
return first_name;
}
public void setFirst_name(String firstName) {
this.first_name = firstName;
}
public String getLast_name() {
return last_name;
}
public void setFirst_name(String lastName) {
this.last_name = lastName;
}
public String getBase_url() {
return base_url;
}
public void setBase_url(String baseUrl) {
this.base_url = baseUrl;
}
}
and the test I wrote is like this
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = { ApplicationProperties.class })
#TestPropertySource(locations="classpath:application.properties")
public class ServiceTests {
#Autowired
private ApplicationProperties applicationProperties;
#Before
private void initializeConfig() {
Mockito.when(applicationProperties.getFirst_name()).thenReturn("Karan");
}
#Test
public void sample_Test() {
MyService myService = new MyService();
String fName = myService.getUserFirstName();
assertEquals(fName, "Karan");
}
}
and the method myService.getUserFirstName is like this
#Service
public class MyService {
#Autowired
private ApplicationProperties applicationProperties;
public String getUserFirstName() {
return applicationProperties.getFirst_name();
}
}
I tried following ways provided in this tutorial and this, this and this stackoverflow questions. But it always have applicationProperties object null in the getUserFirstName method and throws null value exception.
Any suggestion what I am doing wrong.

Related

Why no constraint violations found using javax.validation.Validator? When object not populated with values

multi-tenant-database-config-invalid-no-schema.yml:
tenants:
"001":
tenantId: "001"
configuration:
database:
url: "jdbc:postgresql://localhost:5432/postgres?currentSchema=001"
username: "postgres"
J-Unit class:
public class AppTest {
#Test
public void testInvalid() throws Exception {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
ObjectMapper objectMapper = new ObjectMapper(new YAMLFactory());
File multiTenantConfigurationFile = getMultiTenantTestConfiguration("config/multi-tenant-database-config-invalid-no-schema.yml");
DatabaseEnabledTenants databaseEnabledTenants = objectMapper.readValue(multiTenantConfigurationFile, DatabaseEnabledTenants.class);
Set<ConstraintViolation<DatabaseEnabledTenants>> constraintViolations = validator
.validate(databaseEnabledTenants);
Assertions.assertEquals(0, constraintViolations.size()); // <- Expect this to fail!
}
private File getMultiTenantTestConfiguration(String filename) throws URISyntaxException {
ClassLoader classLoader = getClass().getClassLoader();
URL resource = classLoader.getResource(filename);
File file = new File(resource.toURI());
return file;
}
}
DatabaseEnabledTenants.java:
#Valid
#Component
#ConfigurationProperties(prefix = "multi-tenancy")
public class DatabaseEnabledTenants {
#Valid
#NotNull private Map<String, DatabaseEnabledTenant> tenants = new HashMap<>();
public Map<String, DatabaseEnabledTenant> getTenants() {
return tenants;
}
public void setTenants(Map<String, DatabaseEnabledTenant> tenants) {
this.tenants = tenants;
}
}
DatabaseEnabledTenant.java:
#Valid
public class DatabaseEnabledTenant extends TenantDetails {
#Valid
#NotNull private Configuration configuration;
/** Empty constructor, values populated later. */
public DatabaseEnabledTenant() {}
public Configuration getConfiguration() {
return configuration;
}
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
}
}
Configuration.java:
public class Configuration {
#NotNull private Database database;
public Configuration() {}
public Database getDatabase() {
return database;
}
public void setDatabase(Database database) {
this.database = database;
}
}
Database.java:
public class Database {
#JsonProperty("url")
#NotBlank(message = "RL must not be blank in tenant configuration")
#SchemaNameInJdbcUrlConstraint
private String jdbcUrl;
#NotBlank(message = "Database username must not be blank in tenant configuration")
private String username;
#NotNull(message = "Database password must not be null in tenant configuration")
private String password;
public Database() {}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

#Value working for one class, but not the other

I'm struggling with #Value annotation in my API.
My values are stored in the application.properties file in Spring Boot.
secretKey=trullySecretKey
I created one #Component class for a JWT Key:
#Component
public class SecretKeyProperties {
#Value("${secretKey}")
private String secretKey;
public String getSecretKey() {
return this.secretKey;
}
}
And using it ar my JWT class:
#Service
public class JwtUtil {
#Autowired
SecretKeyProperties secretKeyProperties;
private Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(secretKeyProperties.getSecretKey()).parseClaimsJws(token).getBody();
}...
Works fine.
But when I do exactly the same, but with a Component for Mail properties setup:
#Mail properties
auth=mail.smtp.auth
authValue=true
starttls=mail.smtp.starttls.enable
starttlsValue = true
host=mail.smtp.host
hostValue=smtp.gmail.com
ssl=mail.smtp.ssl.enable
sslValue=true
sender=test#email.com
password=myPassword
The class:
#Component
public class MailProperties {
#Value("${auth}")
private String auth;
#Value("${starttls}")
private String starttls;
#Value("${host}")
private String host;
#Value("${ssl}")
private String SSL;
#Value("${authValue}")
private boolean authValue;
#Value("${starttlsValue}")
private boolean starttlsValue;
#Value("${hostValue}")
private String hostValue;
#Value("${sslValue}")
private boolean sslValue;
#Value("${sender}")
private String sender;
#Value("${password}")
private String password;
public String getAuth() {
return this.auth;
}
public String getStarttls() {
return this.starttls;
}
public String getHost() {
return this.host;
}
public String getSsl() {
return this.ssl;
}
public boolean getAuthValue() {
return this.authValue;
}
public boolean getStarttlsValue() {
return this.starttlsValue;
}
public String getHostValue() {
return this.hostValue;
}
public boolean getSslValue() {
return this.sslValue;
}
public String getSender() {
return this.sender;
}
public String getPassword() {
return this.password;
}
And the implementation:
#Service
public class MessageBuilder {
#Autowired
MailProperties mailProperties;
public static Properties properties;
public static Session session;
public Properties setupProperties(){
Properties properties = new Properties();
properties.put(mailProperties.getAuth(), mailProperties.getAuthValue());
properties.put(mailProperties.getStarttls(), mailProperties.getStarttlsValue());
properties.put(mailProperties.getHost(), mailProperties.getHostValue());
properties.put(mailProperties.getSsl(), mailProperties.getSslValue());
return properties;
}
I get an error
Cannot invoke "com.plaincoded.restapi.configuration.MailProperties.toString()" because "this.mailProperties" is null
It would make sense if it did not work on both occasions, but only in one?
Why could that be?
Update:

When testing mock custom UserDetailsService it returns null when testing a controller that requires authentication

I am looking to Unit Test my controllers on Spring MVC. However, I am unable to properly inject authentication with the #WithUserDetails and my own custom configuration.
The initial error is:
java.lang.IllegalStateException: Unable to create SecurityContext using #org.springframework.security.test.context.support.WithUserDetails(value=username, userDetailsServiceBeanName=userDetailsService)
and this is caused by:
Caused by: java.lang.NullPointerException
at jp487bluebook.app.BluebookUserDetails.(BluebookUserDetails.java:24)
at jp487bluebook.app.BluebookUserDetailsService.loadUserByUsername(BluebookUserDetailsService.java:23)
The class I am using to test:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes={indexController.class, TestSecurityConfig.class})
public class IndexControllerTests {
private MockMvc mockMvc;
#MockBean
QuizRepository quizRepo;
#MockBean
UserRepository userRepo;
#InjectMocks
private indexController indexControllerTest;
#Before
public void setUp() throws Exception {
BluebookUser user = new BluebookUser();
user.setUsername("username");
userRepo.save(user);
mockMvc = MockMvcBuilders.standaloneSetup(indexControllerTest).build();
}
#Test
#WithUserDetails(value = "username", userDetailsServiceBeanName="userDetailsService")
public void mainMapping() throws Exception {
mockMvc.perform(
MockMvcRequestBuilders.get("/")
)
.andExpect(MockMvcResultMatchers.status().isOk());
}
#Test
public void testRedirect() throws Exception {
mockMvc.perform(
MockMvcRequestBuilders.get("/index")
)
.andExpect(MockMvcResultMatchers.status().is(302));
}
}
The index controller:
#Controller
public class indexController {
#Autowired QuizRepository quizRepo;
#Autowired UserRepository userRepo;
#RequestMapping("/index")
public static String indexReDir() {
return "redirect:/";
}
#RequestMapping("/")
public String index(Model model) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
String username = ((BluebookUserDetails)principal).getUsername();
String firstName = ((BluebookUserDetails)principal).getFirstName();
int userId = ((BluebookUserDetails)principal).getUserId();
model.addAttribute("username", username);
model.addAttribute("firstName", firstName);
model.addAttribute("userId", userId);
model.addAttribute("quizzes", quizRepo.findAllPublic());
BluebookUser u = userRepo.findByUsername(username);
model.addAttribute("userClasses", u.getClasses());
List<Notification> list = u.getNotifications();
Collections.reverse(list);
model.addAttribute("notifications", list);
model.addAttribute("socialNumber", u.getFriendRequests().size());
}
return "index";
}
}
The BlueBookUserDetails class:
public class BluebookUserDetails implements UserDetails {
private static final long serialVersionUID = -6205068871475377605L;
private String userName;
private String password;
private String firstName;
private int UserId;
private int userScore;
private List<Classes> classes = new ArrayList<Classes>();
public BluebookUserDetails (BluebookUser user) {
userName = user.getUsername();
password = user.getPassword();
firstName = user.getFirstName();
UserId = user.getId();
classes = user.getClasses();
userScore = user.getUserScore();
}
public BluebookUserDetails () {
}
public int getUserScore() {
return userScore;
}
public void setUserScore(int userScore) {
this.userScore = userScore;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
return authorities;
}
public List<Classes> getClasses() {
return classes;
}
public void setClasses(ArrayList<Classes> classes) {
this.classes = classes;
}
public int getUserId() {
return UserId;
}
public void setUserId(int userId) {
UserId = userId;
}
#Override
public String getPassword() {
return password;
}
#Override
public String getUsername() {
return userName;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
public String getFirstName() {
return firstName;
}}
The BlueBookUserDetailsService Class:
#Service
public class BluebookUserDetailsService implements UserDetailsService {
#Autowired
UserRepository userRepo;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
BluebookUser user = userRepo.findByUsername(username);
return new BluebookUserDetails(user);
}
}
and finally the TestConfiguration:
#TestConfiguration
public class TestSecurityConfig {
#Bean
public BluebookUserDetailsService userDetailsService() {
return new BluebookUserDetailsService();
}
}

Show saved messages from the database MySQL

I created a chat on spring boot. Where several people can correspond. So I created a database and there I store all messages from users. So I want, if a new user enters the chat, then he should see only the last 10 messages. The problem is that the program does not take the last 10 messages from the database, it takes them from the server, this is not correct. I want him to take the last 10 messages from the database.
My code
Rest Controller
#SpringComponent
#org.springframework.web.bind.annotation.RestController
public class RestController {
private List<Message> store;
public RestController() {
store = new ArrayList<>();
}
#PutMapping("/api/save")
public void saveMessage(#RequestBody String chatMessage) {
store.add(new Gson().fromJson(chatMessage, Message.class));
if (store.size() > 10)
store.remove(0);
}
#GetMapping("/api/last")
public String getLasts() {
return new Gson().toJson(store);
}
}
Message class
#Entity
#Table(name = "chatMessages")
public class Message {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String fromV;
private String messageV;
private Timestamp time;
public Timestamp getTime() {
return time;
}
public void setTime(Timestamp time) {
this.time = time;
}
public Message() { }
public String getFromV() {
return fromV;
}
public void setFromV(String fromV) {
this.fromV = fromV;
}
public String getMessageV() {
return messageV;
}
public void setMessageV(String messageV) {
this.messageV = messageV;
}
public Message(String from, String message) {
this.fromV = from;
this.messageV = message;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFrom() {
return fromV;
}
public void setFrom(String from) {
this.fromV = from;
}
public String getMessage() {
return messageV;
}
public void setMessage(String message) {
this.messageV = message;
}
}
MessageRepository
#Repository
public interface MessageRepository extends JpaRepository<Message, Long> {
}
MessageService
public interface MessageService {
void add(Message message);
List<Message> getAllMessages();
}
MessageServiceImpl
#Service
#Transactional
public class MessageServiceImpl implements MessageService {
private final MessageRepository repository;
#Autowired
public MessageServiceImpl(MessageRepository repository) {
this.repository = repository;
}
#Override
public void add(Message message) {
message.setTime(new Timestamp(new Date().getTime()));
repository.saveAndFlush(message);
}
#Override
public List<Message> getAllMessages() {
return repository.findAll();
}
}
MessageList
public MessageList() {
addClassName("message-list");
}
#Override
public void add(Component... components) {
super.add(components);
components[components.length-1]
.getElement()
.callFunction("scrollIntoView");
}
}
Application Controller
server.port=8080
# This is a workaround for https://github.com/vaadin/spring/issues/381
spring.servlet.multipart.enabled = false
spring.datasource.url=jdbc:mysql://localhost:3306/chat?createDatabaseIfNotExist=true&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
To be frankly,i don't understand the purpose of the object store in your controller. If you want to query the last 10 messages.You can just implement a method in repository and invoke it in your controller.
MessageRepository
#Repository
public interface MessageRepository extends JpaRepository<Message, Long> {
List<Message> findTop10ByOrderByTimeDesc();
}

How can I add attachments (Files) to doccuments in couchbase using Spring data JPA in java?

Here's are the links I referred to http://developer.couchbase.com/documentation/mobile/current/develop/guides/couchbase-lite/native-api/attachment/index.html but there is no mention about usage in service or dao classes.
spring doc for couchbase
This is my dao class
#Repository
public interface UserRepository extends CrudRepository<User, String> {
}
Below is my user model
#JsonIgnoreProperties(ignoreUnknown=true)
#Document
public class User implements Serializable {
private static final long serialVersionUID = -6815079861643922076L;
#JsonProperty("docType")
private String docType = "users";
#Id
#JsonProperty("id")
private String id;
#JsonProperty("firstName")
private String firstName;
#JsonProperty("lastName")
private String lastName;
#JsonProperty("password")
private byte[] password;
public String getDocType() {
return docType;
}
public void setDocType(String docType) {
this.docType = docType;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public byte[] getPassword() {
return password;
}
public void setPassword(byte[] password) {
this.password = password;
}
}
this is my service implementation
#Service("userService")
public class UserServiceImpl implements UserService {
#Autowired(required=true)
private UserRepository userRepository;
public User findById(String id) throws Exception {
User user = userRepository.findOne(id.toLowerCase());
return user;
}
public User create(User user MultipartFile file) throws Exception {
String fileName = null;
if (!file.isEmpty()) {
try {
fileName = file.getOriginalFilename();
byte[] bytes = file.getBytes();
}catch (Exception ex) {
}
}
//i want to attach this file as attachment to this user in couch db
User returnUser = userRepository.save(user);
return returnUser;
}
public User update(User user MultipartFile file) throws Exception {
String fileName = null;
if (!file.isEmpty()) {
try {
fileName = file.getOriginalFilename();
byte[] bytes = file.getBytes();
}catch (Exception ex) {
}
}
//i want to attach this file as attachment to this user in couch db
User returnUser = userRepository.save(user);
return returnUser;
}
}
And here is my dbconfig
#Configuration
#EnableCouchbaseRepositories(basePackages="com.repository")
public class DBConfig extends AbstractCouchbaseConfiguration {
#Autowired(required=true)
private PropertyFileReader propertyFileReader;
#Override
protected List<String> bootstrapHosts() {
List<String> couchbaseHostList = Arrays.asList(propertyFileReader.getCouchbaseHostList().split("\\s*,\\s*"));
return couchbaseHostList;
}
#Override
protected String getBucketName() {
String bucketName = propertyFileReader.getCouchbaseBucketName();
return bucketName;
}
#Override
protected String getBucketPassword() {
String bucketPassword = propertyFileReader.getCouchbaseBucketPassword();
logger.debug("bootstrapHosts() : bucketPassword={}", bucketPassword);
return bucketPassword;
}
public CustomConversions customConversions() {
return new CustomConversions(
Arrays.asList(StringToByteConverter.INSTANCE));
}
#ReadingConverter
public static enum StringToByteConverter implements Converter<String, byte[]> {
INSTANCE;
#Override
public byte[] convert(String source) {
return Base64.decodeBase64(source);
}
}
}
Unfortunately I think you are getting Couchbase Server and Couchbase lite mixed up they are two different products.
The spring framework you are using interacts with Couchbase Server, which does not support attachments. You can however save binary blobs in Couchbase.
Couchbase lite does support attachments.

Categories

Resources