Overriding beans in Integration tests - java

For my Spring-Boot app I provide a RestTemplate though a #Configuration file so I can add sensible defaults(ex Timeouts). For my integration tests I would like to mock the RestTemplate as I dont want to connect to external services - I know what responses to expect. I tried providing a different implementation in the integration-test package in the hope that the latter will override the real implementation , but checking the logs it`s the other way around : the real implementation overrides the test one. How can I make sure the one from the TestConfig is the one used?
This is my config file :
#Configuration
public class RestTemplateProvider {
private static final int DEFAULT_SERVICE_TIMEOUT = 5_000;
#Bean
public RestTemplate restTemplate(){
return new RestTemplate(buildClientConfigurationFactory());
}
private ClientHttpRequestFactory buildClientConfigurationFactory() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setReadTimeout(DEFAULT_SERVICE_TIMEOUT);
factory.setConnectTimeout(DEFAULT_SERVICE_TIMEOUT);
return factory;
}
}
Integration test:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = TestConfiguration.class)
#WebAppConfiguration
#ActiveProfiles("it")
public abstract class IntegrationTest {}
TestConfiguration class:
#Configuration
#Import({Application.class, MockRestTemplateConfiguration.class})
public class TestConfiguration {}
And finally MockRestTemplateConfiguration
#Configuration
public class MockRestTemplateConfiguration {
#Bean
public RestTemplate restTemplate() {
return Mockito.mock(RestTemplate.class)
}
}

Since Spring Boot 1.4.x there is an option to use #MockBean annotation to fake Spring beans.
Reaction on comment:
To keep context in cache do not use #DirtiesContext, but use #ContextConfiguration(name = "contextWithFakeBean") and it will create separate context, while it will keep default context in cache. Spring will keep both (or how many contexts you have) in cache.
Our build is this way, where most of the tests are using default non-poluted config, but we have 4-5 tests that are faking beans. Default context is nicely reused

1.
You can use #Primary annotation:
#Configuration
public class MockRestTemplateConfiguration {
#Bean
#Primary
public RestTemplate restTemplate() {
return Mockito.mock(RestTemplate.class)
}
}
BTW, I wrote blog post about faking Spring bean
2.
But I would suggest to take a look at Spring RestTemplate testing support. This would be simple example:
private MockRestServiceServer mockServer;
#Autowired
private RestTemplate restTemplate;
#Autowired
private UsersClient usersClient;
#BeforeMethod
public void init() {
mockServer = MockRestServiceServer.createServer(restTemplate);
}
#Test
public void testSingleGet() throws Exception {
// GIVEN
int testingIdentifier = 0;
mockServer.expect(requestTo(USERS_URL + "/" + testingIdentifier))
.andExpect(method(HttpMethod.GET))
.andRespond(withSuccess(TEST_RECORD0, MediaType.APPLICATION_JSON));
// WHEN
User user = usersClient.getUser(testingIdentifier);
// THEN
mockServer.verify();
assertEquals(user.getName(), USER0_NAME);
assertEquals(user.getEmail(), USER0_EMAIL);
}
More examples can be found in my Github repo here

The Problem in your configuration is that you are using #Configuration for your test configuration. This will replace your main configuration. Instead use #TestConfiguration which will append (override) your main configuration.
46.3.2 Detecting Test Configuration
If you want to customize the primary configuration, you can use a
nested #TestConfiguration class. Unlike a nested #Configuration class,
which would be used instead of your application’s primary
configuration, a nested #TestConfiguration class is used in addition
to your application’s primary configuration.
Example using SpringBoot:
Main class
#SpringBootApplication() // Will scan for #Components and #Configs in package tree
public class Main{
}
Main config
#Configuration
public void AppConfig() {
// Define any beans
}
Test config
#TestConfiguration
public void AppTestConfig(){
// override beans for testing
}
Test class
#RunWith(SpringRunner.class)
#Import(AppTestConfig.class)
#SpringBootTest
public void AppTest() {
// use #MockBean if you like
}
Note: Be aware, that all Beans will be created, even those that you override. Use #Profile if you wish not to instantiate a #Configuration.

#MockBean and bean overriding used by the OP are two complementary approaches.
You want to use #MockBean to create a mock and forget the real implementation : generally you do that for slice testing or integration testing that doesn't load some beans which class(es) you are testing depend on and that you don't want to test these beans in integration.
Spring makes them by default null, you will mock the minimal behavior for them to fulfill your test.
#WebMvcTest requires very often that strategy as you don't want to test the whole layers and #SpringBootTest may also require that if you specify only a subset of your beans configuration in the test configuration.
On the other hand, sometimes you want to perform an integration test with as many real components as possible, so you don't want to use #MockBean but you want to override slightly a behavior, a dependency or define a new scope for a bean, in this case, the approach to follow is bean overriding :
#SpringBootTest({"spring.main.allow-bean-definition-overriding=true"})
#Import(FooTest.OverrideBean.class)
public class FooTest{
#Test
public void getFoo() throws Exception {
// ...
}
#TestConfiguration
public static class OverrideBean {
// change the bean scope to SINGLETON
#Bean
#Scope(ConfigurableBeanFactory.SINGLETON)
public Bar bar() {
return new Bar();
}
// use a stub for a bean
#Bean
public FooBar BarFoo() {
return new BarFooStub();
}
// use a stub for the dependency of a bean
#Bean
public FooBar fooBar() {
return new FooBar(new StubDependency());
}
}
}

With #Primary annotation, Bean overriding works with Spring Boot 1.5.X but fails with Spring Boot 2.1.X it throw error:
Invalid bean definition with name 'testBean' defined in sample..ConfigTest$SpringConfig:..
There is already .. defined in class path resource [TestConfig.class]] bound
Please add below properties= which will instruct Spring explicitly to allow overriding, it is self explainatory.
#SpringBootTest(properties = ["spring.main.allow-bean-definition-overriding=true"])
UPDATE: You can add the same property in application-test.yml (file name depend upon what test profile name you are tests with)

Getting a little deeper into it, see my second answer.
I solved the Problem using
#SpringBootTest(classes = {AppConfiguration.class, AppTestConfiguration.class})
instead of
#Import({ AppConfiguration.class, AppTestConfiguration.class });
In my case the Test is not in the same package as the App. So I need to specify the AppConfiguration.class (or the App.class) explicit. If you use the same package in the test, than I guess you could just write
#SpringBootTest(classes = AppTestConfiguration.class)
instead of (not working)
#Import(AppTestConfiguration.class );
It is pretty wired to see that this is so different. Maybe some one can explain this. I could not find any good answers until now. You might think, #Import(...) is not picked up if #SpringBootTestsis present, but in the log the overriding bean shows up. But just the wrong way around.
By the way, using #TestConfiguration instead #Configuration also makes no difference.

I´ve declared an inner configuration class within my test because I wanted to overwrite just a single method
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class FileNotificationWebhookTest{
public static class FileNotificationWebhookTestConfiguration {
#Bean
#Primary
public FileJobRequestConverter fileJobRequestConverter() {
return new FileJobRequestConverter() {
#Override
protected File resolveWindowsPath(String path) {
return new File(path);
}
};
}
}
}
However,
Declaring the configuration in #SpringBootTest did not work:
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,classes = {FileNotificationWebhookTest.FileNotificationWebhookTestConfiguration.class})
or annotating the test configuration with #Configuration did not work:
#Configuration
public static class FileNotificationWebhookTestConfiguration {
}
and was leading to
Caused by: org.springframework.context.ApplicationContextException:
Unable to start web server; nested exception is
org.springframework.context.ApplicationContextException: Unable to
start ServletWebServerApplicationContext due to missing
ServletWebServerFactory bean.
What did work for me ( contrary to some other posts here) was using #Import
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#Import(FileNotificationWebhookTest.FileNotificationWebhookTestConfiguration.class)
class FileNotificationWebhookTest {
}
Using Spring: 5.3.3 with Spring-Boot-Starter: 2.4.2

#MockBean creates Mockito mock instead of production build.
If you do not want to use Mockito, but provide a replacement in some other way (i.e. by disabling some features of bean with feature toggles), I suggest using combination of #TestConfiguration (since Spring Boot 1.4.0) and #Primary annotation.
#TestConfiguration will load your default context and apply your #TestConfiguration piece in addition to it. Adding #Primary will force your mocked RestTemplate to be injected to it's dependents.
See simplified example below:
#SpringBootTest
public class ServiceTest {
#TestConfiguration
static class AdditionalCfg {
#Primary
#Bean
RestTemplate rt() {
return new RestTemplate() {
#Override
public String exec() {
return "Test rest template";
}
};
}
}
#Autowired
MyService myService;
#Test
void contextLoads() {
assertThat(myService.invoke()).isEqualTo("Test rest template");
}
}

This is super weird.
In my case, (Spring Boot 2.6.7), I could simply #Import MyTestConfiguration containing a custom #Primary #Bean into my #SpringBootTest, and everything worked.
Right until I needed to explicitly name my bean.
Then I suddenly had to resort to
#SpringBootTest(
properties = ["spring.main.allow-bean-definition-overriding=true"],
classes = [MyTestConfig::class],
)

Check this answer along with others provided in that thread.
It's about overriding bean in Spring Boot 2.X, where this option was disabled by default. It also has some ideas about how to use Bean Definition DSL if you decided to take that path.

The simplest solution I found was to set this property in application.properties:
spring.main.allow-bean-definition-overriding=true
This will enable overriding of beans.
Next, create a configuration class in test, and annotate your bean with:
#Bean
#Primary
This way, this bean will override your usual bean when running tests.

Related

Spring boot 2.1 bean override vs. Primary

With Spring Boot 2.1 bean overriding is disabled by default, which is a good thing.
However I do have some tests where I replace beans with mocked instances using Mockito. With the default setting Tests with such a configuration will fail due to bean overriding.
The only way I found worked, was to enable bean overriding through application properties:
spring.main.allow-bean-definition-overriding=true
However I would really like to ensure minimal bean definition setup for my test configuration, which would be pointed out by spring with the overriding disabled.
The beans that I am overriding are either
Defined in another configuration that imported into my test configuration
Auto-discovered bean by annotation scanning
What I was thinking should work in the test configuration overriding the bean and slap a #Primary on it, as we are used to for data source configurations. This however has no effect and got me wondering: Is the #Primary and the disabled bean overriding contradictory?
Some example:
package com.stackoverflow.foo;
#Service
public class AService {
}
package com.stackoverflow.foo;
public class BService {
}
package com.stackoverflow.foo;
#Configuration
public BaseConfiguration {
#Bean
#Lazy
public BService bService() {
return new BService();
}
}
package com.stackoverflow.bar;
#Configuration
#Import({BaseConfiguration.class})
public class TestConfiguration {
#Bean
public BService bService() {
return Mockito.mock(BService.class);
}
}
spring.main.allow-bean-definition-overriding=true can be placed in test configurations. If you need extensive integration testing, you will need to override beans at some point. It's inevitable.
Though the correct answer has already been provided, it implies that your bean will have different names. So, technically, it's not an override.
If you need a real override (because you use #Qualifiers, #Resources or something similar), since Spring Boot 2.X is only possible using the spring.main.allow-bean-definition-overriding=true property.
Update:
Be careful with Kotlin Bean Definition DSL. In Spring Boot it will require a custom ApplicationContextInitializer, like so:
class BeansInitializer : ApplicationContextInitializer<GenericApplicationContext> {
override fun initialize(context: GenericApplicationContext) =
beans.initialize(context)
}
Now if you decide to override one of such DSL-based beans in your test via #Primary #Bean method, it will not do. The initializer will kick in after #Bean methods and you'd still get the initial, DSL-based bean in your tests even with #Primary on the test #Bean.
One other option would be to also create a test initializer for your tests and list them all in your test properties, like so(order matters):
context:
initializer:
classes: com.yuranos.BeansInitializer, com.yuranos.TestBeansInitializer
Bean Definition DSL also supports primary property via:
bean(isPrimary=true) {...}
- which you'll need to eliminate ambiguity when you try to inject a bean, however main:allow-bean-definition-overriding: true is not needed if you go pure DSL way.
(Spring Boot 2.1.3)
Overriding beans means that there may be only one bean with a unique name or id in the context. So you can provide two beans in the following way:
package com.stackoverflow.foo;
#Configuration
public class BaseConfiguration {
#Bean
#Lazy
public BService bService1() {
return new BService();
}
}
package com.stackoverflow.bar;
#Configuration
#Import({BaseConfiguration.class})
public class TestConfiguration {
#Bean
public BService bService2() {
return Mockito.mock(BService.class);
}
}
If you add #Primary then primary bean will be injected by default in:
#Autowired
BService bService;
I make the testing beans available only in test profile, and allow overriding for just while testing, like this:
#ActiveProfiles("test")
#SpringBootTest(properties = {"spring.main.allow-bean-definition-overriding=true"})
class FooBarApplicationTests {
#Test
void contextLoads() {}
}
The bean I am mocking in the test configuration:
#Profile("test")
#Configuration
public class FooBarApplicationTestConfiguration {
#Bean
#Primary
public SomeBean someBean() {
return Mockito.mock(SomeBean.class);
}
}
It is allowed to override #Component with #Bean by default. In your case
#Service
public class AService {
}
#Component
public class BService {
#Autowired
public BService() { ... }
}
#Configuration
#ComponentScan
public BaseConfiguration {
}
#Configuration
// WARNING! Doesn't work with #SpringBootTest annotation
#Import({BaseConfiguration.class})
public class TestConfiguration {
#Bean // you allowed to override #Component with #Bean.
public BService bService() {
return Mockito.mock(BService.class);
}
}

How to restrict inner test #Configuration class to work only for this class?

Base test class for integration testing imports base configuration with component scan that includes almost all packages. In one test class I want to override some beans with Mocs, but this inner configuration is scanned and overrides beans for all tests. Is there some way to avoid this?
I've found the way I like mocking beans with by essentially having a separate MockObjectsConfig class with the mock objects I want using the standard Spring Context Configuration, and then import it alongside my real test config. You can also annotate your mock bean with #Profile and test with #ActiveProfiles if you need to prevent a conflict there.
#Configuration
#Profile("!test")
public class MyRealConfigClass {
#Bean
public YetAnotherClass yetAnotherClass() {
return new YetAnotherClass();
}
}
#Configuration
#Profile("test")
public class MockObjectsConfig {
#Bean
public YetAnotherClass yetAnotherClass() {
Mockito.mock(YetAnotherClass.class); // and add any thenReturns, answers, etc. here
}
}
Then include it in your test like so:
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = { MyRealConfigClass.class, MockObjectsConfig.class)
#ActiveProfiles({"test"})
public class MyJunitTest {
#Autowired
private RestController restController;
}
Then your mock bean will be used and not the real one from the production config.

When running test class, properties can't be read properly from .properties file by using #Value annotation, in Spring Maven project

//Update
After viewing helpful comments, I realize the problem should then be, how to unit test method using values read from properties by #Value .
//
I am working on this issue for days, I am writing unit test for a serviceClass.The serviceClass is like below :
import ...
#Component
public class ServiceClass implements ServiceInterface {
#Value("${data.layer.url}")
private String dataLayerUrl;
#Autowired
private RestTemplate restTemplate
public void dummy(){
restTemplate.postForObject(dataLayerUrl + "/" + ... , ...);
}
}
And CONFIG_DIR is already defined in application configuration file.
I have a SomeConfig class defining beans as below. (...src/main/java/com.app/configuration/SomeConfig)
#Configuration
#ComponentScan(basePackages = {"..."})
#PropertySource(value = "file:${CONFIG_DIR}/app.properties")
public class SomeConfig{
#Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
...
return restTemplate;
}
}
My test class is as below:
Import ...
#Profile("test")
public class ServiceClassTest extends AbstractTest {
#Value("${data.layer.url}")
private String dataLayerUrl;
#InjectMocks
private ServiceClass ServiceClass;
#Mock
RestTemplate restTemplate;
#Before
public void initializeMockito() {
MockitoAnnotations.initMocks(this);
}
#Test
public void dummyTest(){
when(restTemplate.postForObject(dataLayerUrl + "/" + ..., ...)).thenReturn(...);
serviceClass.dummy();
assertEquals(...);
verify(restTemplate).postForObject(...);
}
}
And then my AbstractTest as below :
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles("test")
#SpringApplicationConfiguration(classes = Application.class)
#ContextConfiguration(classes = {TestConfiguration.class})
#ComponentScan(basePackages = ...)
public abstract class AbstractTest {
protected Logger logger = LoggerFactory.getLogger(this.getClass());
}
And I also have .../src/test/resources/application-test.properties defined as below
#Datalayer properties
data.layer.url=http://camel-dev-01.xxx.com:5001
This is the same as defined in application.properties(which locates outside of project in CONFIG_DIR.
The logic of testing is just to make sure when you call dummy method of serviceClass, the postForObject method of restTemplate is called exactly once.
But when doing it this way, I am facing with 2 problems.
when I run test class in debug mode, I found
in ServiceClassTest. dataLayerUrl = "$data.layer.url"
in ServiceClass. dataLayerUrl = null
I researched around and be able to solve problem one by following this link
https://gist.github.com/danlangford/3418696
But this is not an ideal way to do this, since by default spring should be able to read properties from application-test.properties.
And I never figured out what caused the second issue and how to solve it.
I think this would be a common issue when writing unit test on class which read properties from .properties file using $Value annotation. Any comments or suggestions would be very much appreciated.
The key point hear as said M. Deinum is that you use a mix of Spring bean and Mock Object that in this case aren't Spring bean and for this reason can't benefit of the feature of Spring Container such as the injection of the properties.
In particular you should use the spring test abstraction as a "integration test" istruments. With this words I intended that you should use this abstraction, for test the correct configuration, behavior and so on fo your bean in the spring contex. However if you use Stub or mock object you actually exit, of a smal part probably, by the management of spring and the your test don't make sense. Using stub or mock the your test become a Unit test in sense that it will be a test the your bean and functionality in isolation infact you have mock or stub the dependency of your object.
I hope that this reflection could be help you
I am glad to know there is no way to read values from properties by #Value inside a mock obj.
But still my problem is that I want to unit test my dummy method in ServiceClass. Put it another way, as long as I could unit test this method, I don't care whether #Value works or not.
Here is my solution of test method
#Profile("test")
public class ServiceClassTest extends AbstractTest {
#Value("${data.layer.url}")
private String dataLayerUrl;
#InjectMocks
private ServiceClass ServiceClass;
#Mock
RestTemplate restTemplate;
#Before
public void initializeMockito() {
MockitoAnnotations.initMocks(this);
}
#Test
public void dummyTest(){
when(restTemplate.postForObject(anyString() , eq(), eq() )).thenReturn(...);
serviceClass.dummy();
assertEquals(...);
verify(restTemplate).postForObject(anyString(), eq(), eq());
}
By using anyString, I don't rely on what value is read from properties, since I only want to test whether dummy method call restTemplate's postForObject method properly.
You need to add PropertySourcesPlaceholderConfigurer to your test configuration in order to populate properties annotated with #Value annotation. Spring Boot adds it to configuration, but since your test is running without Spring Boot you have to declare it. For more details seehere .
in place of #InjectMocks you can write #Autowired and I thing you can use both annotation like that
Case 1
#InjectMocks
private ServiceClass ServiceClass;
case 2
#Autowired
#InjectMocks
private ServiceClass ServiceClass;
I have same issue but after discussion my senior I have find above like solutions

How can I test only one bean using existing application's spring configuration class?

In my code, I don't want to load all the beans defined in the XXApplicationConfig class.
XXApplicationConfig is a #Configuration annotated file which has bunch of spring beans defined.
So, I want to load only AppBean from XXApplicationConfig class while testing to reduce loading test time and also differentiate what I am testing. I also want to load the class using XXApplicationConfig class to make sure the bean configuration defined is correct as well.
This is my Test class ( modified ) to test AppBean class.
Could you let me know if this is the right approach and suggest how to make it better? Currently, this approach seems to be working. But, not sure if it is correct way of approaching it.
#ContextConfiguration(loader=AnnotationConfigContextLoader.class)
#RunWith(SpringJUnit4ClassRunner.class)
public class ApplicationTest {
#Configuration
#PropertySources(value = {#PropertySource("classpath:test.properties")})
static class MyTestConfiguration {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceHolderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public XXApplicationConfig xxAppConfig() {
return new XXApplicationConfig();
}
#Bean
public CustomTestService customTestService() {
return new CustomTestService();
}
#Bean
public AppBean appBean() throws Exception {
return XXApplicationConfig().appBean();
}
}
#Autowired
private AppBean appBean;
#Test
public void testAppBean() {
test appBean.doSomething();
}
}
If you want to test just one object, just create one object of that class, using the constructor of that class. Spring beans are designed to be POJOs. The Spring context is just a convenient way of creating and connecting objects. Nothing stops you creating and connecting them yourself.
If you can instantiated the class you want to test and manually inject all the dependencies it required via constructor and/or setter getters, then you don't need to use Spring in your test.
However, if your bean:
uses private fields annotated with #Autowired or #Value without corresponding getters/setters.
depends on many other beans.
the behavior you want to test depends on Spring AOP/Proxies (you use #Transactional or #Cacheable for example).
Then you will need Spring to wired the bean. I personally prefer to define a a minimal #Configuration class for these cases.
Then again, if your bean meets the conditions on the list you should consider refactoring the bean to minimize its dependencies and facilitate testing.

Injecting Mockito Mock objects using Spring JavaConfig and #Autowired

I'm trying to replace an #Autowired object with a Mockito mock object. The usual way of doing this was with xml using Springockito:
<mockito:mock id="SomeMock" class="com.package.MockInterface" />
Currently I'm trying to move over to using Spring's JavaConfig to do the job. All of a sudden the Java expressions are a whole lot more verbose than xml:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class MyTestClass {
#Configuration
static class Config {
#Bean
public MockInterface somethingSpecial() {
return Mockito.mock(MockInterface.class);
}
}
#Autowired MockInterface mockObj;
// test code
}
I discovered a library called Springockito-annotations, which allows you to do the following:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader=SpringockitoContextLoader.class)
public class MyTestClass {
#Autowired #ReplaceWithMock MockInterface mockObj;
// test code
}
Clearly, a whole lot prettier :) The only problem is that this context loader doesn't allow me to use #Configuration and JavaConfig for other beans (if I do, Spring complains that there are no candidates that match those autowired fields).
Do you guys know of a way to get Spring's JavaConfig and Springockito-annotations to play nice? Alternatively, is there another shorthand for creating mocks?
As a nice bonus, using Springockito and xml config, I was able to mock out concrete classes without providing autowiring candidates to its dependencies (if it had any). Is this not possible without xml?
Moving away from the now unmaintained (as of this writing) Spingockito-annotations and to Mockito, we have a way of doing this very simply:
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration
public class MyTestClass {
#Mock MockInterface mockObj;
// test code
}
If you're using a real object, but would like to mock a dependency within it, for instance testing a service layer with DAO:
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration
public class MyTestClass {
#InjectMocks RealService;
#Mock MockDAO mockDAO;
// test code
}
Finally, this can also be applied to Spring-boot, but using annotation initialization within setUp() until multiple class runners are supported:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyMainSpringBootClass.class)
public class MyTestClass {
#InjectMocks RealService;
#Mock MockDAO mockDAO;
#Before
public final void setUp() throws Exception{
MockitoAnnotations.initMocks(this);
}
// test code
}
Outdated and deprecated!
Read about mocking and spying in Spring Boot 1.4
Please read also #ethesx answer,
Springockito is unmaintaned
Old answer
This is possible now to mock Spring application without any XML file with Springockito-annotations.. This solution works also with Spring Boot.
import static org.mockito.BDDMockito.*;
import org.kubek2k.springockito.annotations.*;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = Application.class,
loader = SpringockitoAnnotatedContextLoader.class)
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class MainControllerTest {
#Autowired
MainController mainController;
#Autowired
#ReplaceWithMock
FooService fooService;
#Test
public void shouldGetBar() {
//given
given(fooService.result("foo")).willReturn("bar");
//when
Bar bar build = fooService.getBar("foo");
//then
assertThat(bar).isNotNull();
}
}
Dependencies: org.kubek2k:springockito-annotations:1.0.9
It appears that SpringockitoContextLoader extends GenericXmlContextLoader which is described as:
Concrete implementation of AbstractGenericContextLoader that reads bean definitions from XML resources.
So you are limited to xml bean definitions at the moment.
You could write your own context loader, taking relevant parts from the SpringockitoContextLoader class. Take a look here to get started, perhaps you could extend AnnotationConfigContextLoader for example?

Categories