How to autowire Service with-in JUnit Tests - java

How to autowire Service in test class by only using spring-annotations
when I try I got this error below , whereas #Service annotation used in UserServiceImp class
2014-12-20 15:35:52 ERROR TestContextManager:334 - Caught exception
while allowing TestExecutionListener
[org.springframework.test.context.support.DependencyInjectionTestExecutionListener#5af97850]
to prepare test instance [com.amsb.bariz.base.test.UserTest#4520ebad]
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'com.amsb.bariz.base.test.UserTest': Injection
of autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: public com.amsb.bariz.base.service.UserService
com.amsb.bariz.base.test.UserTest.userService; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [com.amsb.bariz.base.service.UserService]
found for dependency: expected at least 1 bean which qualifies as
autowire candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
my Service Class is
package com.amsb.bariz.base.service.imp;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import com.amsb.bariz.base.dao.UserDao;
import com.amsb.bariz.base.dao.UserRoleDao;
import com.amsb.bariz.base.entity.User;
import com.amsb.bariz.base.entity.UserRole;
import com.amsb.bariz.base.service.UserService;
#Service("userService")
public class UserServiceImp implements UserService {
#Autowired
private UserDao userDao;
#Autowired
private UserRoleDao userRoleDao;
public void register(User user) {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
user.setPassword(passwordEncoder.encode(user.getPassword()));
Calendar calendar = Calendar.getInstance();
java.util.Date now = calendar.getTime();
Date dateNow = new Date(20070266);
Timestamp dn = new Timestamp(now.getTime());
user.setStatus("P");
user.setCreated_on(dn);
user.setEnabled(false);
UserRole ur = new UserRole(user,"USER_ROLE");
System.out.println("XDXDX ::" + user.toString());
userDao.create(user);
userRoleDao.create(ur);
}
}
my Test Class is :
package com.amsb.bariz.base.test;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.junit.Test;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
import com.amsb.bariz.base.dao.UserDao;
import com.amsb.bariz.base.entity.User;
import com.amsb.bariz.base.entity.UserRole;
import com.amsb.bariz.base.service.UserService;
import com.github.springtestdbunit.DbUnitTestExecutionListener;
import junit.framework.TestCase;
import junit.framework.TestSuite;
#Configuration
#ComponentScan(basePackages={"com.amsb.bariz.base.service"})
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:spring/spring-main.xml"})
#TestExecutionListeners({DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class,
DbUnitTestExecutionListener.class})
public class UserTest {
#Autowired
public UserService userService;
#Test
public void userAdd() {
User user = new User();
Calendar calendar = Calendar.getInstance();
java.util.Date now = calendar.getTime();
Timestamp doo = new Timestamp(now.getTime());
Date a = new Date(0);
user.setPassword("oman");
user.setName("oman new ");
user.setStatus("N");
user.setCreated_on(doo);
user.setUpdated_on(doo);
user.setDob(new Date(20140522));
user.setUsername("AHMED#A.com");
userService.register(user);
}
}

Are you trying to use the test itself as a part of the Spring configuration? That's not going to work. What you need to do is:
- remove the #Configuration and #ComponentScan annotations from the test itself
- create a simple TestConfiguration class:
#Configuration
#ComponentScan(basePackages={"com.amsb.bariz.base.service"})
#ImportResource("classpath:spring/spring-main.xml")
public class TestConfiguration{ }
And just reference that in your test:
#ContextConfiguration(classes = { TestConfiguration.class }, loader = AnnotationConfigContextLoader.class)
public class UserTest {
And you should be able to inject your service just fine.
Hope it helps.

Related

Description: Field repository in com.example.gcp.GcpApplication required a bean of type 'com.example.gcp.CzlowiekRepository' that could not be found

import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.Bean;
import org.slf4j.Logger;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
public class GcpApplication {
private static final Logger log = LoggerFactory.getLogger(GcpApplication.class);
#Autowired
CzlowiekRepository repository;
public static void main(String[] args) {
SpringApplication.run(GcpApplication.class, args);
}
#Bean
public CommandLineRunner demo(CzlowiekRepository repository) {
return (args) -> {
repository.save(new Person());
log.info("-------------------------------");
for (Person customer : repository.findAll()) {
log.info(customer.toString());
}
log.info("");
};
}
}
package com.example.gcp;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.security.Key;
#Repository
interface CzlowiekRepository extends JpaRepository\<Person, Key\> {}
I get:
APPLICATION FAILED TO START
***************************
Description:
Field repository in com.example.gcp.GcpApplication required a bean of type 'com.example.gcp.CzlowiekRepository' 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.gcp.CzlowiekRepository' in your configuration.

Spring - Autowired is null - Test - UnsatisfiedDependencyException: Error creating bean with name

I'm trying to test my application, I've been trying to solve it for 3 days and I looked for stackoverflow and I still couldn't solve it.
My problem is that Autowired is always null, and even though I import everything suggested as
#RunWith( SpringRunner.class )
#SpringBootTest
public class ESGControllerTest {
#Autowired
private ESGController esgController ;
#Test
public void deveRetornarSucesso_QuandoBuscarLatLong(){
System.out.println(this.esgController);
}
}
or
#RunWith( SpringJUnit4ClassRunner.class )
#ContextConfiguration
public class ESGControllerTest {
#Autowired
private ESGController esgController ;
#Test
public void deveRetornarSucesso_QuandoBuscarLatLong(){
System.out.println(this.esgController);
}
}
is always null and gives this error
EDIT:
ESGController
package br.com.kmm.esgeniusapi.controller;
import br.com.kmm.esgeniusapi.dto.CargaDTO;
import br.com.kmm.esgeniusapi.dto.CargaFilter;
import br.com.kmm.esgeniusapi.entity.AreaEmbargada;
import br.com.kmm.esgeniusapi.entity.Carga;
import br.com.kmm.esgeniusapi.entity.ConfiguracaoCarga;
import br.com.kmm.esgeniusapi.exception.CargaException;
import br.com.kmm.esgeniusapi.inteface.HereReverseGeocode;
import br.com.kmm.esgeniusapi.inteface.HereSearch;
import br.com.kmm.esgeniusapi.service.CargaService;
import br.com.kmm.esgeniusapi.service.ConfiguracaoCargaService;
import br.com.kmm.esgeniusapi.service.IbamaService;
import br.com.kmm.esgeniusapi.service.ReverseGeocodeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;
import javax.annotation.security.RolesAllowed;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
#Slf4j
#RestController
#CrossOrigin(origins = "*", maxAge = 3600)
#RequestMapping("/api/")
#RolesAllowed("VIEW")
#Component
public class ESGController {
#Autowired
ReverseGeocodeService reverseGeocodeService;
#Autowired
IbamaService ibamaService;
#Autowired
CargaService cargaService;
#Autowired
ConfiguracaoCargaService configuracaoCargaService;
#GetMapping(path = "reverse-geocode")
public HereReverseGeocode getRoute(#RequestParam final String location) {
Double lat = Double.parseDouble(location.split(",")[0]);
Double lon = Double.parseDouble(location.split(",")[1]);
return this.reverseGeocodeService.getReverseGeocoding(lat, lon);
}
#GetMapping(path = "search")
public List<HereSearch> search(#RequestParam(name = "q") final String query) {
return this.reverseGeocodeService.search(query);
}
....{
//MORE FUNCTIONS
}
}
I edited and put the ESGController as code for more information.
Is ESGController decorated with #Controller or equivalent so that a bean of that class actually exist in the context?
Is the test class in the same package hierarchy as the rest of the application?
#SpringBootTest by default starts searching in the current package of
the test class and then searches upwards through the package
structure, looking for a class annotated with #SpringBootConfiguration
from which it then reads the configuration to create an application
context.

Spring boot test unable to autowire service class

I am attempting to create a Spring Boot test class which should create the Spring context and autowire the service class for me to test.
This is the error I am getting:
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'com.gobsmack.gobs.base.service.FileImportService' available: expected
at least 1 bean which qualifies as autowire candidate. Dependency
annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
The file structue:
The Test class:
package com.example.gobs.base.service;
import com.example.gobs.base.entity.FileImportEntity;
import com.example.gobs.base.enums.FileImportType;
import lombok.val;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Date;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
#DataJpaTest
#RunWith(SpringRunner.class)
public class FileImportServiceTest {
#Autowired
private FileImportService fileImportService;
private FileImportEntity entity;
The Main application class:
package com.example.gobs.base;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Used only for testing.
*/
#SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
FileImportService interface:
package com.example.gobs.base.service;
import com.example.gobs.base.entity.FileImportEntity;
import com.example.gobs.base.enums.FileImportType;
import java.util.List;
public interface FileImportService {
/**
* List all {#link FileImportEntity}s.
Which is implemented by:
package com.example.gobs.base.service.impl;
import com.example.gobs.base.entity.FileImportEntity;
import com.example.gobs.base.enums.FileImportType;
import com.example.gobs.base.repository.FileImportRepository;
import com.example.gobs.base.service.FileImportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
#Service
#Transactional
public class FileImportServiceImpl implements FileImportService {
#Autowired
private FileImportRepository repository;
#Override
public List<FileImportEntity> listAllFileImportsByType(FileImportType type) {
return repository.findAllByType(type.name());
}
Why can it not find the implementation?
#DataJpaTest annotation doesn't make services loaded to the application context. From Spring documentation: https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-jpa-test
You can use the #DataJpaTest annotation to test JPA applications. By default, it scans for #Entity classes and configures Spring Data JPA repositories. If an embedded database is available on the classpath, it configures one as well. Regular #Component beans are not loaded into the ApplicationContext.
You could use #SpringBootTest annotation instead of DataJpaTest. Hope that helps!

Mapping two #GetMapping to same #RestController into Spring Boot

I need to mapping two GET methods look like:
GET /tickets - Retrieves a list of tickets
GET /tickets/12 - Retrieves a specific ticket
But when I mapped this, the Spring got confused!
When I hit http://localhost:8080/tickets in the Chrome, the result on server is:
DefaultHandlerExceptionResolver : Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: "tickets"]
When I hit http://localhost:8080/tickets/12 in the Chrome, the result on server is:
QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
My Spring controller is:
package wendelsilverio.api.ticket;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
#RestController("tickets")
public class TicketController {
#Autowired
private TicketRepository repository;
#GetMapping
public List<TicketEntity> getTickets() {
return repository.findAll();
}
#GetMapping("/{id}")
public Optional<TicketEntity> getTicket(#PathVariable("id") Long id) {
return repository.findById(Long.valueOf(id));
}
}
My unit test is:
package wendelsilverio.api.ticket;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.Arrays;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
#SpringBootTest
#AutoConfigureMockMvc
#RunWith(SpringRunner.class)
public class TicketControllerRestfulTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private TicketController mockTicketController;
#Test
public void getTickets() throws Exception {
given(mockTicketController.getTickets())
.willReturn(Arrays.asList(new TicketEntity(1L, "First ticket"), new TicketEntity(2L, "Second ticket")));
mockMvc.perform(get("tickets").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(jsonPath("$[0].content", is("First ticket")))
.andExpect(jsonPath("$[1].content", is("Second ticket")));
}
#Test
public void getTicket12() throws Exception {
Optional<TicketEntity> twelveTicket = Optional.of(new TicketEntity(12L, "Twelve ticket"));
given(mockTicketController.getTicket(12L)).willReturn(twelveTicket);
mockMvc.perform(get("tickets/12").contentType(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(jsonPath("$.id", is(12L))).andExpect(jsonPath("$.content", is("Twelve ticket")));
}
}
I'm using Java 11 and Spring Boot 2.1.6
Use
#RestController
#RequestMapping("/tickets")
...
#GetMapping
...
#GetMapping("{id}")
In your code
1) #RestController("tickets") means 'create bean named "tickets"'
2) second URL (#GetMapping("/{id}")) tells 'put ID at root' (http://localhost:8080/ID) - so controller cannot convert 'tickets' to long.

Spring Autowired service and controller not working

I read a lot about this kind of problem here, but it seems my code is good but the autowire is not working :
Error creating bean with name 'optionController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private service.InteractionBanque controllers.OptionController.interactionBanque; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [service.InteractionBanque] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Here is the code of my Controller :
package controllers;
package controllers;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import model.Banque;
import model.Client;
import service.InteractionBanque;
import serviceimpl.InteractionBanqueImpl;
#Controller
public class OptionController {
#Autowired
private InteractionBanque interactionBanque;
#RequestMapping(value="/virement",method=RequestMethod.GET)
public String index(Model model, #ModelAttribute Client client) {
model.addAttribute("virement", new Virement());
return "virement";
}
#RequestMapping(value="/virement",method=RequestMethod.POST)
public String index(#ModelAttribute Virement virement, Model model) {
return "options";
}
}
And the Code of my Service :
package serviceimpl;
import java.util.HashMap;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import dao.BanqueDAO;
import daoimpl.BanqueDaoImpl;
import model.Banque;
import model.Client;
import service.InteractionBanque;
import utils.SendRequest;
#Service
public class InteractionBanqueImpl implements InteractionBanque {
public static final int END_ID_BANQUE = 5;
public static final String LOGIN_URL = "/account";
public boolean connecter(Client client) {
some code
}
}
And The code of the interface :
package service;
public interface InteractionBanque {
boolean connecter(Client client);
}
And my Application class define the #SpringBootApplication which should be use to wire everything :
package controllers;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
SO I don't get it, for me this should do the work but the autowired is not working.
Help would be appreciated :)
#SpringBootApplication scans only package (recursively) within a class that uses it. InteractionBanqueImpl is in another package.
Create a package 'app' with Application class, and then move to it controllers and and other packages. Should be fine.
As #Mati said, you have a problem with packages.
Create a root package for your application and move everything under it, so you have it something like this:
+ myapp
Application.java
+ controller
+ service
+ serviceimpl
The answers you have about putting your Application class in a parent package of the rest of your code will work, but an alternative, if you don't want to change your package structure, would be to use the #ComponentScan annotation, specifying the packages that contain components you want to autowire, for example:
#ComponentScan(basePackages = {"serviceimpl", ...}

Categories