I am learning Junit 5 and test cases. I am using spring boot version '2.2.6.RELEASE and JUnit 5, in my application, I have a method that processes based on the boolean flag from property file.
\src\main\resources\application.properties
#data base connection properties
spring.app.datasource.url=jdbc:mysql://localhost:3306/student_db
spring.app.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.app.datasource.username=root
spring.datasource.password=root
spring.app.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
#additional properties
spring.property.name=shrikant
spring.property.enable=false
database connection properties are used to create the database connection
Datasource.java
@Value("${spring.app.datasource.url}")
private String url;
@Value("${spring.app.datasource.driver-class-name}")
private String className;
@Value("${spring.app.datasource.username}")
private String userName;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.app.jpa.properties.hibernate.dialect}")
private String dialect;
controller class
@RestController
public class Controller {
@Value("${spring.property.name}")
private String name;
@Value("${spring.property.enable}")
private boolean status;
public void validateObject(String surName) {
if (status) { # if this flag is true then only process
System.out.println("name= " + name);
System.out.println("surName= " + surName);
}
}
ControllerTest.java
@SpringBootTest
class ControllerTest {
@Autowired
private Controller controller;
@Test
void show() {
controller.validateObject("sharma");
}
by default the flag is false, so every time test case runs it never processes the object. so I tried to create aplication.properties in the test folder
\src\test\resources\application.properties
spring.property.name=vishal
spring.property.enable=true
but now it's giving me an error that
Could not resolve placeholder 'spring.app.datasource.url'
but I don't want to provide DB connection URL, I am not connecting to the database while testing.
Q1 - how to change the value of properties file for test case only.
Q2 - is it mandatory to provide all the keys of \src\main\resources\application.properties is \src\test\resources\application.properties?
I am new in test case, so little explained answers would be welcomed.
Update:- I found that
@SpringBootTest
@TestPropertySource(properties = {"spring.property.name=vishal", " spring.property.status=true"})
class ControllerTest {
will solve the issue temporarily, by providing keys along with values, but I have a lot of keys, which cannot be provided in such a way.
If you use @SpringBootTest
then your test will load the whole Spring context. This means it will create all your beans and try to wire them together. If you inject property values to your beans, you have to specify them all for such tests as otherwise, you won't be able to boot the application.
What might help you in such a situation is to use test annotations like @WebMvcTest
or @DataJpaTest
to focus on testing just slices of your application. Using @WebMvcTest
you'll get an application context just containing controllers and everything related to your web layer. Other beans (like service classes) can be mocked with @MockedBean
.
Next, for testing business logic in service classes try not to use @SpringBootTest
and rather rely on plain JUnit 5 and Mockito to verify your code.
You still might want to have some integration tests that use @SpringBootTest
to make sure everything is working together. In such case, you can hard code any static property inside application.properties
in src/test/resources/
or using the annotation like you already did: @TestPropertySource(properties = {"spring.property.name=vishal", " spring.property.status=true"})
.
When it comes to providing a database, you can either configure an embedded database (which I would try to avoid) or use the same database as in production. Testcontainers helps you a lot when it comes to providing external infrastructure for your tests like a database.
An example setup with Spring Boot >= 2.2.6 and JUnit might look like the following:
@Testcontainers
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class ApplicationIT {
@Container
public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer()
.withPassword("password")
.withUsername("username");
@DynamicPropertySource
static void postgresqlProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);
registry.add("spring.datasource.password", postgreSQLContainer::getPassword);
registry.add("spring.datasource.username", postgreSQLContainer::getUsername);
}
@Test
public void contextLoads() {
}
}
For Junit5, annotate your test class with path to application.properties
in your src/main/resources
:
@ExtendWith(SpringExtension.class)
@TestPropertySource("classpath:application.properties")
public class MyTest {
@Value("${property.name}")
private int myProperty;
tests...
}
property gets loaded
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.