I am using a spring boot 1.5.4 project where I need a clarification on testing package.
I am seeing Spring Boot comes with #MockBean which is part of org.springframework.boot.test.mock.mockito package.
My question is - Is it similar to Mockito external dependency and I can avoid using Mockito as external dependency as spring boot mock.* package has all features which Mockito has?
As already pointed in Greg's answer , mockito core is already included in spring-boot-starter-test so its already there in your project, no external dependency is needed.
Having said that - mockito's #Mock and Spring's #MockBean are a bit different in a way that #MockBean is basically a #Mock plus #Bean so it does what mockito annotation does plus it works with like a bean too i.e. it places instances in Spring's application context and all other spring bean related concepts come into picture too.
From documentation -
Annotation that can be used to add mocks to a Spring
ApplicationContext. Can be used as a class level annotation or on
fields in either #Configuration classes, or test classes that are
#RunWith the SpringRunner.
Mocks can be registered by type or by bean name. Any existing single
bean of the same type defined in the context will be replaced by the
mock, if no existing bean is defined a new one will be added.
When #MockBean is used on a field, as well as being registered in the
application context, the mock will also be injected into the field.
For non - Spring applications where DI & context are not there, you shoudl use #Mock and for Spring apps , you should use #MockBean.
If you look at the dependencies for spring-boot-starter-test, you'll see that it depends on the Mockito library so it is included for you.
Related
I am trying to write junit test cases for my Spring boot application written in 1.2.5.RELEASE version
I have read the spring boot documentation https://docs.spring.io/spring-boot/docs/1.2.5.RELEASE/reference/htmlsingle/ and trying to write the test case.
Now I want to mock a class which is already a #Primary class in original application.
see the issue here - How to mock a class that been annotated with Primary
On further read I understand that I need to use #MockBean to mock a class which is already a primary in application. But the problem is the spring boot version which I use does not support #MockBean.
I have tried overriding spring-boot-starter-test version alone with 2.1.7.RELEASE(without changing the spring boot parent version as I am not supposed to change the application spring boot version which has many impacts). Now I am able to use #MockBean, but on running the test case, it ends in exception.
java.lang.NoSuchMethodError: org.springframework.core.annotation.AnnotationUtils.getRepeatableAnnotations
How can I use #MockBean in spring boot 1.2.5.RELEASE?
Is there any workaround without using #MockBean?
I have such JUnit 5 test and becuase of test speed I need to disable creating Hazelcast instances while running test. Is there some way how to disable Hazelcast for one particular test?
#SpringBootTest
#RunWith(SpringRunner.class)
class MemoryTradeCommunicatorTest {
// test cases....
}
There are three main ways to approach your problem. I'll assume you just need to disable Hazelcast and that you're using Spring Boot though you don't mention it explicitly.
As Dmitrii mentions, you can mock the bean that provides the Hazelcast instance. Be aware that you'll probably need to split your configuration into multiple fragments so that you can import the beans required in your tests.
You can use Spring profiles. You'd need to create a test profile and create a mock Hazelcast instance inside it. The implementation depends a lot on how you create the real Hazelcast instance (Spring Boot or manually).
Spring Boot creates the Hazelcast instance because of auto-configuration classes. You can prevent this behavior by excluding specific classes. In your case, you'd launch your tests with spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration
You can use #Import for loading only required beans and mock your Hazelcast bean something like that:
#RunWith(SpringRunner.class)
#Import(value = {MemoryTradeCommunicator.class})
#MockBean
private CacheManager cacheManager;
class MemoryTradeCommunicatorTest {
// test cases....
}
Where CacheManager is your Hazelcast realization. Also, don't forget to declare your other needed bean into #Import
I am a python dev and totally new to Spring boot and gradle. However i am fine with java and Trying my best with Kotlin. I was trying to run Spring Boot application(Kotlin) on localhost. Gradle build is working fine except these line
#Configuration
#AutoConfigureAfter(DispatcherServletAutoConfiguration::class)
open class Assembly : WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter()
{
.
.
No value passed for parameter resourceProperties, mvcProperties, beanFactory....
I understand that WebMvcAutoConfigurationAdapter constructor expects these params but should they not be passed automatically through annotation #Configuration and #AutoConfigureAfter .
As i am totally new to spring boot i have no idea what is going wrong and where. As this code is already running in production so i am really confused about whether i am missing some local configuration or gradle conf or something else.
WebMvcAutoConfigurationAdapter isn't intended to be used directly by application code. You should be extending WebMvcConfigurerAdapter instead.
I suspect you've upgraded to Spring Boot 1.4. In that release, WebMvcAutoConfigurationAdapter changed from using field injection to constructor injection. This means that subclasses now need to call the super-constructor passing in the required arguments.
#AutoConfigureAfter only controls the ordering of auto-configuration classes and has no effect on dependency injection. It also only affects auto-configuration classes so may we'll be doing nothing on your Assembly class.
#Configuration doesn't really affect dependency injection either. Configuration classes can have dependencies injected, either into fields annotated with #Autowired or into their constructor. Previously, that constructor also had to be annotated with #Autowired but, as of Spring Framework 4.3 (Spring Boot 1.4), the annotation is unnecessary if the class has a single constructor.
How to Configure Dependency Injection in a Library Project?
Let me illustrate this question with the following example.
Maven Library Project
ReservationAPI
com.example.reservation-api
This project contains a convenience class called ReservationApiClient which uses a RestTemplate (from the Spring Framework) for making HTTP calls.
Is it possible to make the RestTemplate field #Autowired in this library project instead of instantiating it myself?
Maven Executable Project
org.company.application
This project is a Spring Boot application and uses the above ReservationAPI as a dependency. This app will create a #Bean for the convenience class ReservationApiClient contained in that library and will then execute its public methods which in turn make HTTP requests.
What is a good strategy and/or best practices for the scenario described above?
You can do this if you include autowiring in your library project although that means it would always need to be used with a Spring application context to get the value unless you also have getter/setter methods to use as well. However, I don't think using RestTemplate as an autowired object makes sense since there is nothing specific about a RestTemplate and unless you name the beans there is only one bean definition for a class. All of the methods for the RestTemplate require the URI there anyhow. So in this case I would just use the bean for your ReservationApiClient in your application.
One other way to do it is if you want to include Spring dependencies in your library (which I guess you already are by using RestTemplate) you can declare your ReservationApiClient as a #Service or #Component and then use the #ComponentScan annotation in your main Spring Boot project to search that library for components to include in the bean registry.
Another option is to use a feature like Spring Boot's Autoconfigure to create factories that use third party libraries and configure them per properties in your application settings. The auto configuration documentation would be a good place to start with this. You can see the starter projects they have on GitHub and then the associated Autoconfigure classes they have associated with these.
Let me know if any of this does not make sense.
Is it possible to inject Spring beans into an RestEasy #Path class? I managed to do it with Jersey, with #InjectParam annotation, but for some other reasons, I need to switch to RestEasy, and I can't seem to find a way to do it (tried good ol' javax.inject.Inject, but nothing).
EDIT
This solution works:
http://www.mkyong.com/webservices/jax-rs/resteasy-spring-integration-example/
but it's not injection.. I'd still prefer something a little more elegant.
Simply annotate your RestEasy class with Spring's #Component and then inject your beans using Spring's #Autowired. Don't forget to include the annotation-config and component-scan elements in your spring configuration.
There is a working example that integrates RestEasy with Spring just try spring-resteasy.
You could use the #Configurable annotation to make a normal class (created by new) a spring Bean.
Then you can use the normal Spring annotation to inject everything in that class/instance like in a "normal" Spring Bean.
But that requires AspectJ!
#See Spring Reference Chapter 7.8.1 Using AspectJ to dependency inject domain objects with Spring
I totally agree with Peter's answer but there is another way to do it: you make all your exposition beans (RESTEasy or JAX-WS, which are not Spring components) extending the SpringBeanAutowiringSupport.
That way you can easily inject your Spring Services by #Autowired annotation in these classes.