Cannot inject service into Spring test - java

financialReportService is null in REST controller that denotes it fails to inject.
Test:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = SnapshotfindocApp.class)
public class FindocResourceIntTest {
#Inject
private FinancialReportService financialReportService;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
FindocResource findocResource = new FindocResource();
ReflectionTestUtils.setField(findocResource, "findocRepository", findocRepository);
this.restFindocMockMvc = MockMvcBuilders.standaloneSetup(findocResource)
.setCustomArgumentResolvers(pageableArgumentResolver)
.setMessageConverters(jacksonMessageConverter).build();
}
#Test
#Transactional
public void getFinancialRecords() throws Exception {
// Get all the financial-reports
restFindocMockMvc.perform(get("/api/financial-reports"))
.andExpect(status().isOk());
List<Findoc> finReports = financialReportService.getFinancialReports();
for (Findoc fr : finReports) {
assertThat(fr.getNo_months()).isBetween(12, 18);
LocalDate documentTimeSpanLimit = LocalDate.now().minusMonths(18);
assertThat(fr.getFinancial_date()).isAfterOrEqualTo(documentTimeSpanLimit);
}
}
The service:
#Service
#Transactional
public class FinancialReportService {
private final Logger log = LoggerFactory.getLogger(FinancialReportService.class);
#Inject
private FinancialReportDAO financialReportDAO;
public List<Findoc> getFinancialReports(){
return financialReportDAO.getFinancialReports();
}
}
Controller:
#GetMapping("/financial-reports")
#Timed
public List<Findoc> getFinancialReports() {
log.debug("REST request to get financial records");
return financialReportService.getFinancialReports(); // financialReportService is null
}
Update:
The application is generated by JHipster. Then the new service and DAO files were added to enable custom database queries to H2.

After #Injecting the service, you also need to set the field in the setup() method. Adding the below line should solve your problem
ReflectionTestUtils.setField(findocResource, "financialReportService", financialReportService);
On a separate note, the following part of the test looks weird. You are fetching the financial reports twice. This file is the FindocResourceIntTest, so I would remove any direct calls to financialReportService.
// Get all the financial-reports
restFindocMockMvc.perform(get("/api/financial-reports"))
.andExpect(status().isOk());
List<Findoc> finReports = financialReportService.getFinancialReports();

Related

How to write unit test for URI create in java

Below is the method I'm trying to write unit test using junit 5
#Value("${proxy.host}")
private String endpoint;
public Request<Void> setAwsRequestGETParameter(String setStatusPath) {
Request<Void> requestAws = new DefaultRequest<Void>("sts");
requestAws.setHttpMethod(HttpMethodName.GET);
requestAws.setEndpoint(URI.create(endpoint));
requestAws.setResourcePath(setStatusPath);
return requestAws;
}
Below is the unit test I'm trying to run
#InjectMocks
private AWSAuthHandler testAWSAuthHandler;
#Test
public void testSetAwsRequestGETParameter() throws Exception {
URI mockedURI = Mockito.mock(URI.class);
assertNotNull(testAWSAuthHandler.setAwsRequestGETParameter("/status/7deaed5e-3080-45ec-89ba-403977d60c0c"));
}
Below is the stack trace:
java.lang.NullPointerException
at java.base/java.net.URI$Parser.parse(URI.java:3106)
at java.base/java.net.URI.<init>(URI.java:600)
at java.base/java.net.URI.create(URI.java:881)
Can someone please help me with the missing part? Thank you
For setting properties of class that you can't mock you can use Spring Reflection Utils, like that:
ReflectionUtils.setField(field, target, value);
where the field is the name of the field which you want to set ("endpoint" for your case),
target is the mocked class (testAWSAuthHandler for your case)
value is the wanted value
As Sweta Sharma said, you need to initialise AWSAuthHandler with some value for endpoint field. That's why it is better to use constructor injection rather than field one.
Assuming your AWSAuthHandler class look like this (as you didn't provide the code for the whole class):
public class AWSAuthHandler {
#Value("${proxy.host}")
private String endpoint;
public Request<Void> setAwsRequestGETParameter(String setStatusPath) {
Request<Void> requestAws = new DefaultRequest<Void>("sts");
requestAws.setHttpMethod(HttpMethodName.GET);
requestAws.setEndpoint(URI.create(endpoint));
requestAws.setResourcePath(setStatusPath);
return requestAws;
}
You can refactor it in the following way:
public class AWSAuthHandler {
private String endpoint;
public AWSAuthHandler(#Value("${proxy.host}") String endpoint) {
this.endpoint = endpoint;
}
public Request<Void> setAwsRequestGETParameter(String setStatusPath) {
Request<Void> requestAws = new DefaultRequest<Void>("sts");
requestAws.setHttpMethod(HttpMethodName.GET);
requestAws.setEndpoint(URI.create(endpoint));
requestAws.setResourcePath(setStatusPath);
return requestAws;
}
Then you can create tests for this class:
private AWSAuthHandler testAWSAuthHandler;
#BeforeEach
void setUpTests() {
this.testAWSAuthHandler = new AWSAuthHandler("some-endpoint-here");
}
#Test
public void testSetAwsRequestGETParameter() throws Exception {
assertNotNull(testAWSAuthHandler.setAwsRequestGETParameter("/status/7deaed5e-3080-45ec-89ba-403977d60c0c"));
}
You can read more about Spring #Value annotation here, for example: https://www.baeldung.com/spring-value-annotation

How to write a mocked unit test for a db insert method in Springboot REST API?

I have a REST API written in Spring Boot.
Now I want to create unit tests with JUnit and Mockito that mock the database operations.
Here is the endpoint that inserts a new customer to the db.
#RestController
public class CustomerController {
#Autowired
private CustomerRepository customerRepository;
#PostMapping(value="/customers", produces = "application/json")
public ResponseEntity<Customer> addCustomer(#RequestBody Customer customer){
Customer newCustomer = customerRepository.save(customer);
return new ResponseEntity<Customer>(newCustomer, HttpStatus.OK) ;
}
Test:
#Test
public void testAddCustomer() {
Customer customer = Mockito.mock(Customer.class);
customer.setIdCustomer(1L);
customer.setName("Pete");
customer.setAge(35);
customer.setEmail("pete#test.com");
when(customerRepository.save(customer)).thenReturn((Customer) Stream.of(customer));
CustomerController customerController = new CustomerController();
ResponseEntity<Customer> respCustomer = customerController.addCustomer(customer);
assertTrue(respCustomer.getBody().getIdCustomer() != null);
}
I'm getting a null pointer exception on the following line:
when(customerRepository.save(customer)).thenReturn((Customer) Stream.of(customer));
Use
#Mock
private CustomerRepository customerRepository
in your test and configure the repository using mockito API
it should be something like this
#Test
public void testFindTheGreatestFromAllData() {
DataService dataServiceMock = mock(DataService.class);
when(dataServiceMock.retrieveAllData()).thenReturn(new int[] { 24, 15, 3 });
SomeBusinessImpl businessImpl = new SomeBusinessImpl(dataServiceMock);
int result = businessImpl.findTheGreatestFromAllData();
assertEquals(24, result);
}

Test the service in springboot

This is the service I have :
#Service
public class UserInfoService {
#Autowired
private UserInfoServiceClient UserInfoServiceClient; // Call another Rest API
public ResponseEntity<ResponseUserInfoData> sendUserInfo(String UserId) throws RuntimeException {
ResponseUserInfoData responseUserInfoData = new ResponseUserInfoData();
//Get the body from the User service client
UserServiceDTO UserServiceDTO = UserInfoServiceClient.sendResponse(UserId).getBody();
//Set the values of responseUserInfoData
Optional<UserServiceDTO> UserServiceDTOOptional = Optional.ofNullable(UserServiceDTO);
if (UserServiceDTOOptional.isPresent()) {
UserServiceDTOOptional.map(UserServiceDTO::getId).ifPresent(responseUserInfoData::setid);
}
else return ResponseEntity.noContent().build();
}
}
I have to test it. I'm new to JUnit testing. I want to test the following points:
To check if the service return the response entity
To check if the get and set method works
This is what I started?
#RunWith(MockitoJUnitRunner.class)
public class ServiceTests {
#InjectMocks
private UserInfoService UserInfoService;
#Mock
private UserInfoServiceClient UserInfoServiceClient;
#Mock
private UserServiceDTO UserServiceDTO;
#Test
public void shouldReturnUserInfoData() throws IOException{
UserInfoService.sendUserInfo("ABC");
}
}
Any help is appreciated?
Mockito is useful to mock the dependencies of the service so that you can test all the code path in you service. In your case you will want to stub the call to serInfoServiceClient.sendResponse(UserId) and have it return a specific UserServiceDTO for each test case.
The test file looks like it is set up correctly, you only need to mock the method to give you the result you need for the particular test, for example
#RunWith(MockitoJUnitRunner.class)
public class ServiceTests {
#InjectMocks
private UserInfoService UserInfoService;
#Mock
private UserInfoServiceClient UserInfoServiceClient;
#Test
public void shouldReturnUserInfoData() throws IOException{
final String userId = "123";
// The mocked return value should be set up per test scenario
final UserServiceDto dto = new UserServiceDto();
final ResponseEntity<UserServiceDTO> mockedResp = new ResponseEntity<>(dto, HttpStatus.OK);
// set up the mock service to return your response
when(UserInfoServiceClient.sendResponse(userId)).thenReturn(mockedResp);
// Call your service
ResponseEntity<ResponseUserInfoData> resp = UserInfoService.sendUserInfo(userId);
// Test the result
Assert.isNotNull(resp);
}
}
There are also other ways to mock the dependencies using Mockito. I suggest going through the quick start of https://site.mockito.org/

Getting blank response in spring rest controller unit test cases

I have written unit test cases for a spring rest controller for below put method
#PutMapping("/offers/{jobTitle}")
public Offer updateOffer(#PathVariable String jobTitle,#Valid #RequestBody Offer offer) {
return offerService.updateNoOfPost(jobTitle, offer);
}
Below is my service class
#Override
public Offer updateNoOfPost(String jobTitle, Offer offer) {
if(!offerRepository.existsById(jobTitle))
throw new ResourceNotFoundException("JobTitle "+jobTitle+" not found !!");
offer.setNoOfPost(offer.getNoOfPost());
return offerRepository.save(offer);
}
I have written the unit test case for this method using testNg and mockito
public class OfferControllerTest {
private MockMvc mvc;
private JacksonTester<Offer> jsonOffer;
#Mock
private OfferService service;
#InjectMocks
OfferController offerController;
private Offer offer;
#BeforeMethod
public void setup() {
offer = new Offer("LSE", new Date(),1);
MockitoAnnotations.initMocks(this);
mvc = MockMvcBuilders.standaloneSetup(offerController)
.build();
JacksonTester.initFields(this, new ObjectMapper());
}
#Test
public void updateOffer() throws Exception {
Mockito.when(service.updateNoOfPost("LSE", offer)).thenReturn(offer);
MockHttpServletResponse response = mvc.perform(
put("/offers/LSE").contentType(MediaType.APPLICATION_JSON).content(
jsonOffer.write(new Offer("SE", new Date(), 19)).getJson()
)).andReturn().getResponse();
assertThat(response.getContentAsString()).isEqualTo(new ObjectMapper().writeValueAsString(offer));
}
I am getting response code as 200. but getting blank body.pls find error below
FAILED: updateOffer
org.junit.ComparisonFailure: expected:<"[{"jobTitle":"LSE","createdAt":"2018-10-27","noOfPost":1}]"> but was:<"[]">
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
what am i missing ? is this the standard way of writting unit test cases for spring rest controller ?
Below mocking should fix the issue
Mockito.when(service.updateNoOfPost(Mockito.any(String.class), Mockito.any())).thenReturn(offer);
Read more here: stack-46914252

Apache Camel Default Transaction Manager Data Not Seen in Route

I have two routes in Apache Camel. I am using Spring 3 and JPA annotations through Hibernate.
I have multiple data sources and have configured Apache Camel to use one default TransactionManager through SpringTransactionPolicy.
I save the data using DAO and can see the data within the test class by actually finding data. I then use the same DAO within Apache Camel Processor to find the same data, but the data is not found. I don't see why within the test class the data can be found and as soon as I try to look in the Apache Camel custom processor the data cannot be found.
Below is the sample code:
public class Config {
#Autowired
private TransactionManagerConfig transactionManagerConfig;
#Bean
public SpringTransactionPolicy defaultTransactionPolicy() throws Exception {
SpringTransactionPolicy transactionPolicy = new SpringTransactionPolicy();
transactionPolicy.setTransactionManager((PlatformTransactionManager) transactionManagerConfig.transactionManager());
return transactionPolicy;
}
}
public class CustomRouter extends SpringRouteBuilder {
public void configure() throws Exception {
ApplicationContext applicationContext = getApplicationContext();
from("someSource")).transacted().unmarshal().jaxb("com.sample.processor.entities").convertBodyTo(Entity.class).to("direct:x")
.end();
from("direct:x").transacted().process((CustomProcessor) applicationContext.getBean("customProcessor")).to(someSource);
}
}
public class CustomProcessor implements org.apache.camel.Processor {
#Resource
private StatusDAO statusDAO;
public CustomProcessor(StatusDAO statusDAO) {
this.statusDAO = statusDAO;
}
public void process(Exchange exchange) throws Exception {
Status status = null;
Message message = exchange.getIn();
Entity entity = (Entity) message.getBody();
if(entity.getId() != null) {
// find by id
status = statusDAO.findById(id);
}
status.setName("someName");
messageStatusDAO.update(status);
message.setBody(messageStatus);
exchange.setOut(message);
}
}
Data is received within the system as XML and changed to a Entity class. I find data using the statusDAO.findById() at this point the DAO returns no data even though the Entity exists.
I setup the test as below:
#Transactional
#TransactionalConfiguration(defaultRollback = true)
public class CustomTest {
#Transactional
#Before
public void setup throws Exception {
// setup the Status entity and save it using the DAO
}
#Test
public void testSomething() {
Status status = statusDAO.findById("id"); // returns the Status that was saved
MockEndpoint mockEndpoint = (MockEndpoint) this.context.getEndpoint(someDestination);
mockEndpoint.expectedMessageCount(1);
Status status = producerTemplate.requestBody(source, someXML, Status.class);
assertNotNull(status);
mockEndpoint.assertIsSatisfied();
}
}
Using the same transaction manager and the same statusDAO within the Custom Processor does not return the status.
I don't understand why.

Categories