2

I have a Spring bean that reads a configuration property value from application.yml

public class AutoDisableRolesService {

    @Value("${cron.enabled}")
    private boolean runTask;
    // remainder of class omitted
}

In the application.yml this property is set to false

cron:
  enabled: false

But when I run the test, I want it to be true. I've tried the following, but it does not seem to work

@SpringBootTest(properties = { "cron.enabled=true" })
@ExtendWith(MockitoExtension.class)
public class AutoDisableRolesServiceTests {
    
    @Mock
    private UserRoleRepository userRoleRepository;

    @InjectMocks
    private AutoDisableRolesService autoDisableRolesService;
    // remainder of test class omitted
}

I've also tried the following, without success

@ContextConfiguration(classes = AutoDisableRolesService.class)
@TestPropertySource(properties = "cron.enabled=true")
@ExtendWith(MockitoExtension.class)
public class AutoDisableRolesServiceTests {

    @Mock
    private UserRoleRepository userRoleRepository;

    @InjectMocks
    private AutoDisableRolesService autoDisableRolesService;
    // remainder of test class omitted
}
3
  • Try using a @TestPropertySource Commented Jul 7, 2021 at 16:19
  • @Michiel any chance you could flesh that out into an answer? Commented Jul 7, 2021 at 16:32
  • I've misread your initial question, it isn't related to test properties. Commented Jul 7, 2021 at 16:37

1 Answer 1

2

You're mixing up two types of test set ups; A Spring boot test setup with a Mockito test set up. By using @InjectMocks on your class under test, Mockito instantiates the class and injects all the fields annotated with @Mock, bypassing the Spring TestApplicationContext setup.

Either use a Spring test set up using:

@SpringBootTest(properties = { "cron.enabled=true" })
public class AutoDisableRolesServiceTests {
    
    @MockBean
    private UserRoleRepository userRoleRepository;

    @Autowired
    private AutoDisableRolesService autoDisableRolesService;

    // remainder of test class omitted
}

Or a mockito set up using:

public class AutoDisableRolesServiceTests {
    
    @Mock
    private UserRoleRepository userRoleRepository;

    @InjectMocks
    private AutoDisableRolesService autoDisableRolesService;

    @BeforeEach
    public void setUp() {
        ReflectionTestUtils.setField(autoDisableRolesService, "runTask", true);
    }
}

[edit]

If you don't need a full @SpringBootTest set up, use

@ExtendWith(SpringExtension.class)
@TestPropertySource(properties={"cron.enabled=true"})
@ContextConfiguration(classes = { AutoDisableRolesService.class})
public class AutoDisableRolesServiceTests {
    
    @MockBean
    private UserRoleRepository userRoleRepository;

    @Autowired
    private AutoDisableRolesService autoDisableRolesService;

    // remainder of test class omitted
}

The difference between @SpringBootTest and @ExtendsWith(SpringExtension.class) is that a @SpringBootTest loads the full (test)ApplicationContext while the latter only loads a partial context, which is faster but doesn't include everything.

Sign up to request clarification or add additional context in comments.

4 Comments

How would I inject AutoDisableRolesService and mock its depenencies when using the third approach?
Thanks a lot for your help, would you be able to add a line or two explaining the difference between the SpringBootTest and SpringExtension approaches?
It seems you can load a partial application context with @SpringBootTest(classes = {AutoDisableRolesService.class}) or by combining @SpringBootTest with @ContextConfiguration(classes = { AutoDisableRolesService.class}). I wonder if there's any difference between these approaches and @ExtendWith(SpringExtension.class) ?
The difference is that, while both set ups you mention only include the given class, a SpringBootTest als loads additional configuration you would have in a normal ApplicationContext (also known as test slices). For instance, in a non-SpringBootTest, a PropertySourcesPlaceholderConfigurer is not automatically loaded.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.