6

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.

2 Answers 2

6

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() { } } 
Sign up to request clarification or add additional context in comments.

Comments

4

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

1 Comment

I'm using spring-boot-starter-test 2.5.15 and this does not work

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.