After updating to Spring Boot 2.6.8 with Java v11 and using Junit5 I'm not able to Mock anymore MongoTemplate
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes={RepositoryImpl.class})
class RepositoryImplTest {
#Autowired
private RepositoryImpl repositoryImpl;
#MockBean
private MongoTemplate db;
...
}
I get the following error
java.lang.IllegalStateException: Failed to load ApplicationContext Caused by: org.mockito.exceptions.base.MockitoException: Mockito cannot mock this class: class org.springframework.data.mongodb.core.MongoTemplate.
as per dependency I have in pom.xml
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</dependency>
Related
I would like to test my controller class. But I couldn't manage to run springBootTest class. My project written in spring boot. We are writing REST API using spring boot.
When I try to excute following test class. I still get following line from terminal.
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import static org.assertj.core.api.Assertions.assertThat;
/*
*
* #A Sabirov Jakhongir
*
*/
#SpringBootTest
#WebMvcTest
public class PrivilegesControllerTest {
#Autowired
private PrivilegesController privilegesController;
#Test
public void add() {
assertThat(privilegesController).isNotNull();
}
}
I put here all needed dependency for testing from my project.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-launcher -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.3.2</version>
<scope>test</scope>
</dependency>
What might be cause of not working of test Class.
With Junit5 and #SpringBootTest will load the full application, I had faced the same issue before, you can find details about the question here and answer here.
The solution for this is to use your test without #SpringBootTest.
The solution to your test class is as below.
#ExtendWith(MockitoExtension.class)
public class PrivilegesControllerTest {
#InjectMocks
private PrivilegesController privilegesController;
#Test
public void add() {
assertThat(privilegesController).isNotNull();
}
}
You can also use #ExtendWith(SpringExtension.class) instead of #ExtendWith(MockitoExtension.class)
To test spring boot application is creating your controller, use #SpringBootTest annotation, and to test the behavior or responsibility of the controller is better to use #WebMvcTest. No need to annotate both the annotation to one class.
There are two cases to test the controller's responsibility.
With running Server
Without Server
For 1st Case, you can use #SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) to start a server with a random port.
For 2nd Case, use #WebMvcTest for testing the web layer.
All the test cases are written with the following signature:
#Test
public void test_Name() throws Exception {
//your test definition
}
You can also read the Official Documentation of Spring Boot https://spring.io/guides/gs/testing-web/
I have the following error coming up:
Exception: Error creating bean with name 'inventoryService' defined in URL [jar:file:/app.jar!/BOOT-INF/classes!/com/epi/services/inventory/items/InventoryService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'itemRepository': Cannot resolve reference to bean 'databaseClient' while setting bean property 'databaseClient'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'databaseClient' available
2019-06-18 18:38:41,409 INFO [main] org.apache.juli.logging.DirectJDKLog: Stopping service [Tomcat]
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.catalina.loader.WebappClassLoaderBase (jar:file:/app.jar!/BOOT-INF/lib/tomcat-embed-core-8.5.29.jar!/) to field java.lang.Thread.threadLocals
WARNING: Please consider reporting this to the maintainers of org.apache.catalina.loader.WebappClassLoaderBase
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2019-06-18 18:38:45,424 INFO [main] org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-06-18 18:38:50,695 ERROR [main] org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.epi.services.inventory.items.InventoryService required a bean named 'databaseClient' that could not be found.
Action:
Consider defining a bean named 'databaseClient' in your configuration.
My application has the following classes and dependencies:
Inside main module:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-postgresql</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
</dependency>
<dependency>
<groupId>myGroupId</groupId>
<artifactId>myModule.dblib</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectreactor</groupId>
<artifactId>reactor-spring</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
</dependency>
</dependencies>
App:
#SpringBootApplication(scanBasePackages = "com.pack")
#EntityScan("com.pack")
#EnableR2dbcRepositories
#Import(DatabaseConfiguration.class)
public class InventoryApplication {
public static void main(String[] args) {
SpringApplication.run(InventoryApplication.class, args);
}
}
Service:
#Service
#RequiredArgsConstructor
public class InventoryService {
private final ItemRepository itemRepository;
public Flux<ItemPojo> getAllItems() {
return itemRepository.findAllItems()
.map(Item::toPojo);
}
}
Repo:
#Repository
public interface ItemRepository extends ReactiveCrudRepository<Item, Long> {
Flux<List<Item>> findByName(String name);
#Query("select i from Item i")
Flux<Item> findAllItems();
}
Entity:
#Data
#Table(name = "items")
public class Item implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
public static ItemPojo toPojo(final Item items) {
return new ItemPojo(items.id, items.name);
}
}
myModule.dblib:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-r2dbc</artifactId>
</dependency>
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectreactor</groupId>
<artifactId>reactor-spring</artifactId>
</dependency>
</dependencies>
Database config:
#Configuration
#EnableR2dbcRepositories
public class DatabaseConfiguration {
#Value("${spring.data.postgres.host}") private String host;
#Value("${spring.data.postgres.port}") private int port;
#Value("${spring.data.postgres.database}") private String database;
#Value("${spring.data.postgres.username}") private String username;
#Value("${spring.data.postgres.password}") private String password;
#Bean
public PostgresqlConnectionFactory connectionFactory() {
return new PostgresqlConnectionFactory(PostgresqlConnectionConfiguration.builder()
.host(host)
.port(port)
.database(database)
.username(username)
.password(password)
.build());
}
}
What am I missing?
im going to shamelessly plug my own article about how to get started with R2DBC postgres and spring boot.
R2DBC getting started
I think your problem lies in how you initiate your database connectionFactory. According to the documentation you need to extend and override the AbstractR2dbcConfiguration#connectionFactory
#Configuration
#EnableR2dbcRepositories
public class PostgresConfig extends AbstractR2dbcConfiguration {
#Override
#Bean
public ConnectionFactory connectionFactory() {
return new PostgresqlConnectionFactory(
PostgresqlConnectionConfiguration.builder()
.host("localhost")
.port(5432)
.username("postgres")
.password("mysecretpassword")
.database("myDatabase")
.build());
}
}
Official documentation
This approach lets you use the standard io.r2dbc.spi.ConnectionFactory instance, with the container using Spring’s AbstractR2dbcConfiguration.
As compared to registering a ConnectionFactory instance directly, the configuration support has the added advantage of also providing the container with an ExceptionTranslator implementation that translates R2DBC exceptions to exceptions in Spring’s portable DataAccessException hierarchy for data access classes annotated with the #Repository annotation.
This hierarchy and the use of #Repository is described in Spring’s DAO support features.
AbstractR2dbcConfiguration registers also DatabaseClient that is required for database interaction and for Repository implementation.
Official R2DBC documentation
Turns out I needed to have my Database configuration class extend AbstractR2dbcConfiguration which includes the DatabaseClient bean.
From a TDD approach, I worked from trying to get the following TestNG method to work:
#Test
#Slf4j
#SpringBootTest
class PostgresSanityTesting extends AbstractTestNGSpringContextTests{
#Autowired
DatabaseClient databaseClient
void sanityCheck() {
assert databaseClient
}
But to get there, there's some work...
First, I'm not seeing any effective code unless I forced my gradle subproject to build with
ext['spring.version'] = '5.2.0.M2'
which in fact is called out in the R2Dbc documentation. And half of the other dependencies are coming in from spring experimental and milestones. So "buyer beware"... (e.g. I'm still not seeing R2dbc correctly handle repository save(), and a series of other problems.)
As to the instant coding problem:
Given the correct set up, the database client is a #Bean configured as part of the AbstractR2dbcConfiguration class, and then that TestNg test will pass.
But I found that I needed to still create a #Bean, and I inject the connection factory parameters via #ConfigurationProperties. I separate those concerns in two files, as placing the #Bean in with the subclass of AbstractR2dbcConfiguration just didn't work for me.
Here's the code I'm using, expressed in groovy.
import io.r2dbc.spi.ConnectionFactory
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile
import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration
import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories
#Configuration
class R2DbcConfiguration extends AbstractR2dbcConfiguration {
private final ConnectionFactory connectionFactory
R2DbcConfiguration( ConnectionFactory connectionFactory ) {
this.connectionFactory = connectionFactory
}
#Override
ConnectionFactory connectionFactory() {
this.connectionFactory
}
}
and
import io.r2dbc.postgresql.PostgresqlConnectionConfiguration
import io.r2dbc.postgresql.PostgresqlConnectionFactory
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "spring.datasource")
class PostgresConnectionConfig{
String database
String username
String password
String host
String port
#Bean
PostgresqlConnectionFactory connectionFactory() {
final def dbPort = port as Integer
PostgresqlConnectionConfiguration config = PostgresqlConnectionConfiguration.builder() //
.host(host)
.port(dbPort)
.database(database)
.username(username)
.password(password).build()
PostgresqlConnectionFactory candidate = new PostgresqlConnectionFactory(config)
candidate
}
}
and part of my application.yml
spring:
datasource:
url: jdbc:postgresql://127.0.0.1:5432/postgres
driver-class-name: org.postgresql.Driver
driverClassName: org.postgresql.Driver
database: postgres
host: localhost
port: 5432
password: pokey0
username: postgres
and excerpts from my subproject's build.gradle
repositories {
maven { url "https://repo.spring.io/libs-milestone" }
}
dependencies {
implementation group: 'org.springframework.data', name: 'spring-data-releasetrain', version: 'Lovelace-RELEASE', ext: 'pom'
implementation group: 'org.springframework.data', name: 'spring-data-r2dbc', version: '1.0.0.M2'
implementation group: 'io.r2dbc', name: 'r2dbc-postgresql', version: '1.0.0.M7'
implementation('org.springframework.boot:spring-boot-starter-webflux')
implementation('io.projectreactor:reactor-test')
implementation group: 'org.postgresql', name: 'postgresql', version: '42.2.5'
implementation('org.springframework.boot:spring-boot-starter-actuator')
testImplementation('org.springframework.boot:spring-boot-starter-test')
implementation group: 'javax.persistence', name: 'javax.persistence-api', version: '2.2'
}
I am using the following spock dependency
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.0-groovy-2.4</version>
<scope>test</scope>
</dependency>
I wrote this test
class JsonIncludeResolverTest extends Specification {
JsonIncludeResolver uut;
def "test"(){
expect:
true
}
}
the test succeeds
Now I want to use Spring to inject JsonIncludeResolverwithin the specification.
JsonIncludeResolver is annotated with #Component and is injected successfully when running the application. Both tests and component are placed in the same maven module.
I read about spring-spock here: How to inject spring beans into spock test
Therefore I added this dependency version
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-spring</artifactId>
<version>1.1-groovy-2.4</version>
<scope>test</scope>
</dependency>
after adding this dependency running the s
Exception in thread "main" java.lang.NoSuchMethodError: org.spockframework.util.ReflectionUtil.isAnnotationPresentRecursive(Ljava/lang/Class;Ljava/lang/Class;)Z
at org.spockframework.spring.SpringExtension.isSpringSpec(SpringExtension.java:83)
at org.spockframework.spring.SpringExtension.visitSpec(SpringExtension.java:59)
at org.spockframework.runtime.ExtensionRunner.runGlobalExtensions(ExtensionRunner.java:46)
at org.spockframework.runtime.ExtensionRunner.run(ExtensionRunner.java:40)
at org.spockframework.runtime.Sputnik.runExtensionsIfNecessary(Sputnik.java:88)
at org.spockframework.runtime.Sputnik.getDescription(Sputnik.java:55)
at com.intellij.junit4.JUnit4IdeaTestRunner.getDescription(JUnit4IdeaTestRunner.java:78)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:50)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
I then tried to use the proper annotations
#ContextConfiguration
class JsonIncludeResolverTest extends Specification {
#Autowired
JsonIncludeResolver uut;
def "test"(){
expect:
uut != null
}
}
Still the result is the above exception.
The groovy test is under /src/test/groovy which is a working as you could see in the first successful run of the test.
Try upgrading Spock to 1.1 as follows:
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.1-groovy-2.4</version>
<scope>test</scope>
</dependency>
org.spockframework.util.ReflectionUtil.isAnnotationPresentRecursive() has been introduced since version 1.1 by this commit.
I'm trying to test my application following samples on the Spring website.
These are my dependencies:
dependencies {
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile("org.springframework.boot:spring-boot-starter-security")
compile('org.springframework.boot:spring-boot-starter-web')
compile("org.springframework.boot:spring-boot-starter-thymeleaf")
compile("org.thymeleaf.extras:thymeleaf-extras-springsecurity4")
runtime('org.springframework.boot:spring-boot-devtools')
runtime('com.h2database:h2')
runtime('mysql:mysql-connector-java')
compileOnly('org.projectlombok:lombok')
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile('org.springframework.security:spring-security-test')
}
And this is the test class:
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class ProductControllerTest {
#Autowired
private MockMvc mockMvc;
#Test
public void testHomePage() throws Exception {
this.mockMvc.perform(get("/")).andDo(print()).andExpect(status().isOk());
}
}
I get the error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
java.lang.IllegalStateException: Failed to load ApplicationContext
Any idea what may be causing this? I don't have any specific configuration files, only the a security configuration and a webconfig.
Webconfig:
public class WebConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**", "/css/**", "/fragments/**")
.addResourceLocations("classpath:/static/images/", "classpath:/static/css/", "classpath:/fragments/");
}
}
The following line in the output:
java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
Tells us that the class javax.xml.bind.JAXBException is not found.
As #Antot mentionned, adding the following dependency to your graddle should fix the issue:
compile('javax.xml.bind:jaxb-api:2.3.0')
For those using Maven, use the following:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
I'm writing a test for a Spring boot Rest controller. This rest controller writes some values to the db.
I want to use in-memory database which Spring provides for this test. According to this doc I have to annotate the test class with #DataJpaTest, which causes this error:
java.lang.IllegalStateException: Failed to load ApplicationContext
Further down in the error stack trace I see the following exception was thrown:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Failed to replace DataSource with an embedded database for tests. If you want an embedded database please put a supported one on the classpath or tune the replace attribute of #AutoconfigureTestDatabase.
This is the test class which I'm working on:
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
#DataJpaTest
public class AuthenticationControllerFTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private AuthenticationManager authenticationManager;
#Autowired
private WebApplicationContext context;
#Autowired
private Filter springSecurityFilterChain;
#Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context)
.addFilters(springSecurityFilterChain).build();
}
#Test
public void testCreate() throws Exception {
String exampleUserInfo = "{\"name\":\"Salam12333\",\"username\":\"test#test1.com\",\"password\":\"Salam12345\"}";
RequestBuilder requestBuilder = MockMvcRequestBuilders
.post("/signup")
.accept(MediaType.APPLICATION_JSON).content(exampleUserInfo)
.contentType(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = result.getResponse();
int status = response.getStatus();
Assert.assertEquals("http response status is wrong", 200, status);
}
}
What is causing this error ?
Edit 1
This is the content of my application.properties:
spring.datasource.username = hello
spring.datasource.password = hello
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/myproject?useSSL=false
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
logging.level.org.springframework.web=DEBUG
server.port = 8443
server.ssl.key-store = classpath:tomcat.keystore
server.ssl.key-store-password = hello
server.ssl.key-password = hello
server.ssl.enabled = true
server.ssl.key-alias=myproject
Edit 2
I added the following to my pom.xml:
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>test</scope>
</dependency>
I created application-test.properties with the following content:
spring.datasource.username= root
spring.datasource.password= password
spring.datasource.driver-class-name= org.h2.Driver
spring.datasource.url= jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
What is the username and passowrd ? Where should I set them ?
I also added #ActiveProfiles("test") to the test class, when I run the test I get an error which includes this line :
Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
Assuming you annotate class with #SpringBootApplication, which enables auto-configuration and you have H2 dependency on classpath(see below) Spring Boot will see H2 in-memory database dependency and it will create javax.sql.DataSource implementation. Default connection URL is jdbc:h2:mem:testdb and the default username and password are: username: sa and password: empty.
application.properties file
spring.datasource.url=jdbc:h2:mem:tesdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
spring.jpa.show-sql = true
spring.h2.console.enabled=true // if you need console
H2 Dependency
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency> // If you need h2 web console
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
You can gain access to h2 console for management http://localhost:8080/h2-console
For Testing REST service with in-memory DB, you need to following things:
1. Add h2 dependency in pom.xml
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
2. Define h2 configuration in application.properties or application.yaml
spring.jpa.database = h2
spring.datasource.url=jdbc:hsqldb:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create
3. Annotate you test class
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
Complete code will be like:
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class AuthenticationControllerFTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private AuthenticationManager authenticationManager;
#Autowired
private WebApplicationContext context;
#Autowired
private Filter springSecurityFilterChain;
#Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context)
.addFilters(springSecurityFilterChain).build();
}
#Test
public void testCreate() throws Exception {
String exampleUserInfo = "{\"name\":\"Salam12333\",\"username\":\"test#test1.com\",\"password\":\"Salam12345\"}";
RequestBuilder requestBuilder = MockMvcRequestBuilders
.post("/signup")
.accept(MediaType.APPLICATION_JSON).content(exampleUserInfo)
.contentType(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = result.getResponse();
int status = response.getStatus();
Assert.assertEquals("http response status is wrong", 200, status);
}
}
Remove both annotations #AutoConfigureMockMvc and #DataJpaTest. You are trying to test the complete applciation, so need the #SpringBootTest annotation. #DataJpaTest is only needed if you want to test only the data apllication slice. Have a look at this: https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4
In spring boot we do not require to add any thing additional for in memory database configuration except for jar file on class path and application property file (application.properties) on the class path (src/test/resources if maven is used) rest of the things will be taken care by spring boot (beauty of boot).
Another option is to provide profile specific properties file on the class path src/amin/resources (for example application-test.properties)
Both of the file are valid for test configurations
Sample configuration for property file is given below (consider HSQL DB jar on class path):
spring.jpa.hibernate.ddl-auto = create-drop
spring.jpa.database = HSQL
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.HSQLDialect
spring.datasource.driverClassName = org.hsqldb.jdbcDriver
spring.datasource.url: jdbc:hsqldb:mem:scratchdb
spring.datasource.username = sa
spring.datasource.password = pass
Maybe this helps.
spring.datasource.url=jdbc:hsqldb:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create
See also Configure specific in memory database for testing purpose in Spring
I believe, you can use below in-memory db with integration test -
This will also help if you are using json[b](though it is in DB2 but some ops like inserting/updating not support with our code) datatype or any other field that is not present in DB2 (compatibility issue).
Then refer this TestContainer - Stackoverflow answer
Pom.xml
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.15.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.15.1</version>
<scope>test</scope>
</dependency>
XyzIT.java
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ActiveProfiles("test")
#Testcontainers
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
#Test
void test(){
var mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/opportunities/process")
.header("emailId", "ravi.parekh#xyz.com")
.header("Authorization", "authorization")
.header("Content-Type", "application/json").content(objectMapper.writeValueAsString(opportunity))).andReturn();
}
Application-test.yml
datasource:
initialization-mode: always
schema: classpath*:schema-h2.sql #initial sql script to createDB
url: jdbc:tc:postgresql:11.9:///
jpa:
hibernate.ddl-auto: none
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
default_schema: public
show-sql: true