I am new to DataBase testing and I am trying to Connect the database by using tag #SpringBootTest in class level and by using Autowire, It is not creating instantiation getting always null
#SprintBootTest
Class Test{
#Autowire
DatabaseService databaseService;
}
Can anyone suggest please? If any one did similar like this , can you please give me the instructions
There are multiple ways to test your database and here is a couple of them,
Using In-memory-database(ex: H2) using test scope
It's quite good to use h2(in-memory-DB) for mimicking the database. Though it is not mandatory and we can use mockito to mock the database interactions as well.
Add these dependencies,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.196</version>
<scope>test</scope>
</dependency>
Now your test class should look like this,
#RunWith(SpringRunner.class)
#SpringBootTest(classes = YourApp.class, webEnvironment = RANDOM_PORT)
Class DatabaseServiceTest{
#Autowired
private DatabaseService databaseService;
}
Replicating actual database configuration properties
First, you need to replicate your properties/yml from main/resources to test/resources directory. Your test class remains the same as given in the above approach. But make sure that you excluded the h2-dependency from your pom.
Please explore these tutorials as well,
spring integration testing
spring boot test
junit and mockito example
Related
I am able to run a Spring Boot application with Camunda for workflow management. My pom.xml with Camunda related dependencies are shown below.
<dependencyManagement>
...
<dependency>
<groupId>org.camunda.bpm</groupId>
<artifactId>camunda-bom</artifactId>
<version>7.15.0</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter</artifactId>
<version>7.15.0</version>
</dependency>
<!-- REST API -->
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
<version>7.15.0</version>
</dependency>
<!-- dashboard -->
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
<version>7.15.0</version>
</dependency>
<dependency>
<groupId>org.camunda.bpm</groupId>
<artifactId>camunda-engine-plugin-spin</artifactId>
</dependency>
<dependency>
<groupId>org.camunda.spin</groupId>
<artifactId>camunda-spin-dataformat-all</artifactId>
</dependency>
I have just one .BPMN file. My application.yml file looks like this:
spring.main.banner-mode: console
server.port: 9090
springdoc:
model-and-view-allowed: true
swagger-ui:
operationsSorter: alpha
spring.jpa:
hibernate:
ddl-auto: none
show-sql: true
properties:
hibernate:
format_sql: true
spring.datasource:
initialization-mode: always
platform: postgres
url: jdbc:postgresql://xxxx
username: xxxx
password: xxxx
spring.flyway.enabled: false
camunda.bpm:
admin-user:
id: demo
password: demo
generic-properties:
properties:
generalResourceWhitelistPattern: "[a-zA-Z0-9,'_\\$\\-\\.\\+\\!\\*\\(\\)]+|camunda-admin"
In the codes, all I have to do are just to declare the Camunda objects and I can used them without further setups:
#AutoWired
protected final RuntimeService runtimeService;
#AutoWired
protected final TaskService taskService;
#AutoWired
protected final IdentityService identityService;
Now I am trying to write unit tests. It seems that there are more than one way to set up Camunda for unit testing, but I am not able to get any of the examples I found working. By some trial and error, I managed to get the following codes to set up Camunda for unit test.
#ActiveProfiles("test")
public class EntitlementServiceTest {
private RuntimeService runtimeService;
private TaskService taskService;
private IdentityService identityService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ProcessEngine processEngine = ProcessEngineConfiguration.createStandaloneInMemProcessEngineConfiguration()
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE)
.setJdbcUrl("jdbc:h2:mem:database_user;DB_CLOSE_ON_EXIT=FALSE")
.setJobExecutorActivate(true)
.buildProcessEngine();
runtimeService = processEngine.getRuntimeService();
taskService = processEngine.getTaskService();
identityService = processEngine.getIdentityService();
}
...
}
But I am not sure if this is the correct way to do so, so it would be better if someone points this out. The codes don't seem to have loaded anything from the application file for unit testing, application-test.yml. Replacing the hardcoded JDBC URL with ${spring.datasource.url} does not work at all. And even though I have set the camunda.bpm.generic-properties.properties.generalResourceWhitelistPattern, application-test.yml, it is obvious that it is not being read.
You have basically two ways to test a camunda spring boot application:
1st: run a camunda engine in memory, without spring. This can be very useful to test process flows, delegate behavior and so on. In that case, you will use the "ProcessEngineRule" from the core (junit4 style) or the junit5 extension (camunda-bpm-junit5). You will probably mock a lot of services and repos because you focus on the camunda flow. You do not need to annotate with "ActiveProfiles", as you are not running a spring context.
2nd: Run your tests using the SpringRunner or the SprinExtension and let spring handle the engine setup. This is just a plain spring boot test which will run everything you specify via yml and profiles and you will be able to inject all the camunda services.
Neither of these approaches is "better", they focus on different things. According to the testing pyramid, you would have many "real" unit tests, that do not even run camunda in memory just to verify your code works, some rule-based flow tests and a few integration tests using spring boot tests.
The camunda best practices guide will help configuring the scenarios: https://camunda.com/best-practices/testing-process-definitions/
Sidenote: When you mix plain-unit and spring integration tests, you should switch to constructor based injection to make it easier to manually create instances of your services without using reflection.
I'm trying to ensure that one Spring Boot Starter is loaded before another. In this case, I have a custom spring boot starter written by my organization and the spring-boot-starter-data-jpa starter. It's crucial that the custom starter's bean is ran before spring-boot-starter-data-jpa is initialized. An example snippet of the dependencies in pom.xml:
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>spring-boot-starter-my-customer-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
How would one go about this? The solution I'm currently considering is adding a #Primary annotation to the top of the bean initialized in my company's custom starter, not sure if this would work and looking for best practice here. The bean I'm attempting to load in the custom starter before spring-boot-starter-jpa's beans are loaded is responsible for setting proxy settings, therefore must be loaded first so that traffic to the database can be routed via proxy.
Not really sure as to what you are trying to achieve here, but a way of controlling bean creation could be done using the DependsOn annotation.
In you case, since you would like to initialize your custom bean before the actual database connection is made, I think that adding this to your database configuration class should be enough.
I have a Spring Boot project with SQL/Web dependencies. I have controllers and models but NO configuration classes. This is a very simple project so I'm doing simple authentication by checking user-specific tokens in the request headers. I would like to use the BCrypt dependency to hash passwords before saving them into my database, but Spring Boot won't let me simply use the static functions.
I have added these three dependencies to my pom.xml:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
And created an endpoint in my controller just to check the output of the static hashpw function.
#GetMapping("/bcrypt/{pw}")
public String crypt(#PathVariable String pw)
{
return BCrypt.hashpw(pw, "xxwv");
}
But now that I added those 3 dependencies, it keeps redirecting me to a login page that I never created. I just want to use the static hashing functions without Spring Boot adding random security I never asked for.
Adding following exclude parameter to the annotation of my Application class solved the problem:
#SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
Edit: I've been told by my lead that the test that called the class I was having issues with utilized BPMS and that BPMS is no longer used for the project. Thank you for all of the replies.
Background:
I'm working with an existing codebase, which still isn't fully functional. Specifically, I've been tasked with getting the project's unit tests completed, but I've had no previous experience with Spring or dependency managers at all.
Problem:
The code given below is causing my tests to not compile, saying there's no qualifying bean of ProducerTemplate.
#Component
public class QueueService {
#Produce
private ProducerTemplate producerTemplate;
public QueueService(ProducerTemplate producerTemplate) {
this.producerTemplate = producerTemplate;
}
}
I'm sorry if this is a dumb question, but I haven't been able to find another instance of this in a question.
Stack Trace
Spring Boot component provides auto-configuration for Apache Camel. For integration using Apache Camel you must add a starter dependency:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>2.22.1</version>
</dependency>
See here for more info. A tutorial on the subject.
I am trying to mock the final class which is available in our company's internal library using Mockito 2.18.3 framework, unfortunately we don't have access to change the code in the library. But whenever I run I get below error:
java.lang.NoClassDefFoundError: Could not initialize class org.mockito.Mockito
at org.springframework.boot.test.mock.mockito.MockReset.get(MockReset.java:107)
at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:69)
at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.resetMocks(ResetMocksTestExecutionListener.java:55)
at org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener.afterTestMethod(ResetMocksTestExecutionListener.java:50)
at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:319)
This is my dependency:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.18.3</version>
<scope>test</scope>
</dependency>
This is the test class:
#RunWith(SpringRunner.class)
#TestPropertySource("classpath:application-test.properties")
#SpringBootTest
public class JwtTokenTest {
#Autowired
private class JwtValidatorService jwtValidatorService;
#Mock
private JwtTokenDetails jwtTokenDetails;
#Test
public void jwtGenerateTest() {
//Code to test JWT generation
}
}
Also as per this link: https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#unmockable I have created org.mockito.plugins.MockMaker file with contents: mock-maker-inline.
I tried searching in other Stackoverflow posts and Google, but still not solution. Can anyone kindly help me in this? Looks like I am missing something, but failed to identify it. Since I don't have much expertise in Mockito, tried to use powermock but it is posing different challenges in downloading dependencies in company's network.
Please let me know if I need to add more code or more details.
Spring Boot 1.5.11 is compatible with Mockito 1.x. Specifically, it uses 1.10.19. Rather than overriding the version of Mockito to a new major version, you should let Spring Boot's dependency management specify the version. Doing so will ensure that you use a compatible version. If Mockito 1.10 doesn't meet your needs, you'll need to find an alternative solution.
Spring Boot uses Mockito 1.x by default. However, it's possible to override it with Mockito 2.x, as Spring Boot can also use it without any problems (see this commit).
To do so, just add this modification to your POM file properties:
<properties>
<mockito.version>2.18.3</mockito.version>
</properties>