Spring Boot Integration Tests, #Autowired works, #Inject does not, Why? - spring-boot

I work on a Spring Boot application, I have written a Service and I want to test this Service in an Integration Test. Therefor I want to Inject the Service Into my test. If I use the #Inject annotation, The Service is null. If I use #Autowired, the Service gets Injected and the test works. I thought the annotation should do more or less the same, with the only differrence that #Autowired fails if no bean is available, because it is default set to required=true.The Service has an Interface and I choose the implementation based on Field Name.
Interface:
import org.springframework.core.io.ByteArrayResource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;
public interface FileService {
boolean storeDicomZip(InputStream stream, long caseId);
.
.
.
}
Implementation:
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import java.io.*;
import java.nio.file.Files;
import java.util.Optional;
#Service
public class FileSystemFileService implements FileService {
.
.
.
}
And The Test:
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#IntegrationTest
public class FileSystemFileServiceTest {
#Autowired
private FileService fileSystemFileService;
#Test
public void storeDicomZip() throws Exception {
InputStream stream = new ByteArrayInputStream("TEST".getBytes());
fileSystemFileService.storeDicomZip(stream, 3);
Assert.assertTrue(fileSystemFileService.getDicomZipVersions(3) == 1);
}
.
.
.
}
As described, If I use #Autowired, like here it works, if I use #Inject it does not because fileSystemFileService is null.
Does somebody know why this is the case, and what I have to change to use #Inject?

Related

RestAssured, H2, SpringBootTest Transaction Management. Persisted data not available when calling REST Interface

I wrote a simple SpringBootTest where I tried to read test data from a JSON file and insert it into the database in the #BeforeEach annotated method. When querying the data in the test method, I indeed find the data in the repository. When the REST interface is called via RestAssured and the corresponding method is executed, no data is found via the respository. However, when setting rollback=false in the test, I can find the data in the H2 database. Test code as follows:
package mypackage;
import static io.restassured.RestAssured.get;
import static org.hamcrest.Matchers.hasItems;
import static org.mockito.ArgumentMatchers.eq;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Objects;
import mypackage.MessageEntity;
import mypackage.MessageRepo;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.restassured.RestAssured;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
#EnableAutoConfiguration
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { "spring.main.lazy-initialization=true",
"spring.datasource.url=jdbc:h2:file:C:/mydatabase", "spring.jpa.properties.hibernate.default_schema=",
"spring.jpa.hibernate.ddl-auto=create", "spring.datasource.driverClassName=org.h2.Driver",
"spring.jpa.properties.hibernate.show_sql=true", "spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect",
"spring.datasource.username=sa" })
#ActiveProfiles("test")
class MyWebServiceTest{
#Autowired
MessageRepo messageRepo;
#LocalServerPort
int port;
#Autowired
private PlatformTransactionManager platformTransactionManager;
#BeforeEach
void beforeAll() throws IOException, URISyntaxException {
RestAssured.baseURI = "http://localhost/webservice";
RestAssured.port = port;
TransactionTemplate transactionTemplate = new TransactionTemplate(this.platformTransactionManager);
final List<MessageEntity> messages = setupMessages();
transactionTemplate.execute((TransactionCallback<Object>) status -> messageRepo.saveAllAndFlush(messages));
}
#Test
#Transactional
#Rollback(false)
void test() {
System.out.println(messageRepo.findAll()); // successfully retrieves data
get("/messages").then().assertThat().body("$", hasItems(67)).and().statusCode(eq(200)); // in the corresponding method of the WebService, no data is found
}
private List<MessageEntity> setupMessages() throws IOException, URISyntaxException {
final String messagesString = Files.readString(
Paths.get(Objects.requireNonNull(MyWebServiceTest.class.getResource("/messages.json")).toURI()));
return new ObjectMapper().readValue(messagesString, new TypeReference<List<MessageEntity>>() {
});
}
}
I tried to persist the data in the #BeforeEach in different ways, tried flushing etc, but the data is not available when doing messageRepo.findAll() in the method called in the REST-Interface. I would expect the inserted data to be also available there. However, the data is available in the test method, but not at the REST endpoint.
Do you have any idea why this is happening and what I can try to get the desired result with my test data? Thanks!

Asking me for CucumberContextConfiguration when I already have

I currently working on integration testing of one the Restful APIs. I have received an exception asking me to annotate a glue class using #CucumberContextConfiguration. At the moment, I have
ApplicationTests.java
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import io.cucumber.spring.CucumberContextConfiguration;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
#RunWith(Cucumber.class)
#CucumberContextConfiguration
#SpringBootTest(classes = {VehicleRegApplication.class,
VehicleRegApplicationTests.class,
CucumberSpringConfiguration.class})
#CucumberOptions(features = "src/test/resources/Features",
glue = {"com.vehiclereg.StepDefinitions"},
plugin = {"pretty"})
public class VehicleRegApplicationTests {
#Test
void contextLoads() {
}
}
CucumberSpringConfiguration.java in the same folder as the ApplicationTests.java
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
#CucumberContextConfiguration
#SpringBootTest
#AutoConfigureMockMvc
public class CucumberSpringConfiguration {
}
I have cucumber-java, cucumber-spring, cucumber-junit, junit injected. I have done what the exception says and when I run the test the same error comes back.
io.cucumber.core.backend.CucumberBackendException: Please annotate a glue class with some context configuration.
I wonder if I have done something wrong?

Spring not picking up RestController endpoint

I have my spring project setup as shown below, but I am getting a 404 on the /custom endpoint. All answers I've found similar to this problem highlighted that the controller layer needs to be in a package below the project layer however I have it set out like this so I'm unsure why Spring isn't recognising the endpoint.
package com.myproject.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("custom")
public class CustomPathController {
#GetMapping
public ResponseEntity<Void> test() {
return new ResponseEntity<>(HttpStatus.OK);
}
}
package com.myproject;
import com.ryantenney.metrics.spring.config.annotation.EnableMetrics;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#EnableMetrics
#EnableJpaRepositories
#SpringBootApplication
public class MyProject {
public static void main(String[] args) {
SpringApplication.run(MyProject.class, args);
}
}
There must have been a port clash as a PC restart has fixed the issue

Integration test with jersey and spring boot 1.4.0.RELEASE

I am trying to write integration test with jersey, Spring boot 1.4 and Spring data jpa.I am able to start embedded server but getting error from jersey side , any help will be appreciated.
Integration test
import static org.assertj.core.api.Assertions.assertThat;
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.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT, classes=Application.class)
public class ContactServiceIT {
#Autowired
private TestRestTemplate restTemplate;
#Autowired
private ContactDao contactDao;
#Test
public void mergeContactsTest() {
String body = this.restTemplate.getForObject("/contacts/merge", String.class);
assertThat(body).isEqualTo("contacts merged");
}
}
Contact Resource
import java.io.IOException;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import org.springframework.beans.factory.annotation.Autowired;
#Path("/contacts")
public class ContactResource {
#Autowired
private ContactService contactService;
#GET
#Path("merge")
public Response mergeContacts() throws IOException {
contactService.mergeContacts();
return Response.status(Response.Status.CREATED)
.entity("contacts merged").build();
}
}
Stack trace:
java.lang.NoSuchMethodError: org.glassfish.jersey.CommonProperties.getValue(Ljava/util/Map;Ljavax/ws/rs/RuntimeType;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
at org.glassfish.jersey.jackson.JacksonFeature.configure(JacksonFeature.java:73) ~[jersey-media-json-jackson-2.23.1.jar:na]
at org.glassfish.jersey.model.internal.CommonConfig.configureFeatures(CommonConfig.java:680) ~[jersey-common-2.7.jar:na]
at org.glassfish.jersey.model.internal.CommonConfig.configureMetaProviders(CommonConfig.java:610) ~[jersey-common-2.7.jar:na]
at org.glassfish.jersey.server.ResourceConfig.configureMetaProviders(ResourceConfig.java:800) ~[jersey-server-2.7.jar:na]
Please let me know if I am missing something.
Thanks.

Post url seems not been called with spring security

My issue is that, when I call the url http://localhost:8080/site/data/gouv/ with postman with corresponding form data parameters, nothing happens. It seems even the call is not catched by the controller because there is no log.
Postman page
Here is the controller :
package com.mintad.spring.controllers;
import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.site.common.beans.Gouv;
import com.site.common.service.GouvService;
import au.com.bytecode.opencsv.CSVReader;
#RestController
#RequestMapping("/data")
public class DataController {
#Autowired
private GouvService gouvService;
#RequestMapping(value = "/gouvernorate", method = RequestMethod.POST)
public ResponseEntity<Gouv> addGouvernorate(#RequestBody Gouv gouv) throws IOException {
gouvService.addGouv(gouv);
return new ResponseEntity<Gouv>(gouv, HttpStatus.OK);
}
}
I've tried to call the url with Jsoup as follows :
String base64login = new String(Base64.encode("sof:1".getBytes()));
Document docs = Jsoup.connect("http://localhost:8080/site/data/gouv/").header("Authorization", "Basic " + base64login).
data("name", "name").
data("delegation", "delegation").
data("district", "district").
data("postalCode", "postalCode").post();
But in vain.
Any help please ? I'm using spring security 4.0.4.RELEASE and Spring 4.2.5.RELEASE

Resources