Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock absent bean definitions in SpringJUnit4ClassRunner?

I have a Spring 4 JUnit test which should verify only a particular part of my application.

@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:context-test.xml")
@ActiveProfiles("test")
public class FooControllerIntegrationTest {
     ...
}

So I don't want to configure and instantiate all those beans which are actually aren't involved into the scope of my test. For example I don't want to configure beans which are used in another controller which I am not going to test here.

However, because I don't want to narrow component-scan pathes, I get "No qualifying bean of type" exception:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [...

Is any way how to ignore such missed definitions if I certainly sure that they aren't involved into the functionality I am testing?

like image 569
Andremoniy Avatar asked Mar 06 '18 06:03

Andremoniy


People also ask

Can you mock a bean?

We can use the @MockBean to add mock objects to the Spring application context. The mock will replace any existing bean of the same type in the application context.

How do you inject a mock in SpringBootTest?

If you want to create just a Mockito test you could use the annotation @RunWith(MockitoJUnitRunner. class) instead of @SpringBootTest . But if you want to create a Spring Boot integration test then you should use @MockBean instead of @Mock and @Autowired instead of @InjectMocks .

What is the difference between @MockBean and @mock?

tl;dr: Use @Mock when unit testing your business logic (only using JUnit and Mockito). Use @MockBean when you write a test that is backed by a Spring Test Context and you want to add or replace a bean with a mocked version of it.

How do you override a spring bean?

Bean Overriding Spring beans are identified by their names within an ApplicationContext. Thus, bean overriding is a default behavior that happens when we define a bean within an ApplicationContext which has the same name as another bean. It works by simply replacing the former bean in case of a name conflict.


1 Answers

Is any way how to ignore such missed definitions if I certainly sure that they aren't involved into the functionality I am testing?

No, there is no automated or built-in mechanism for such a purpose.

If you are instructing Spring to load beans that have mandatory dependencies on other beans, those other beans must exist.

For testing purposes, the best practices for limiting the scope of which beans are active include modularization of your config (e.g., horizontal slicing that allows you to selectively choose which layers of your application are loaded) and the use of bean definition profiles.

If you're using Spring Boot, you can then also make use of "testing slices" or @MockBean/@SpyBean in Spring Boot Test.

However, you should keep in mind that it's typically not a bad thing to load beans that you are not using in a given integration test, since you are (hopefully) testing other components that in fact need those beans in other test classes within your test suite, and the ApplicationContext would then be loaded only once and cached across your different integration testing classes.

Regards,

Sam (author of the Spring TestContext Framework)

like image 77
Sam Brannen Avatar answered Sep 18 '22 14:09

Sam Brannen