Spring tests shutting down standalone wiremock server - spring

I have some end-to-end UI tests with WebDriver that use a remote wiremock instance, that I connect to in the following way:
#Configuration
public class WireMockConfiguration {
#Bean
public WireMock wireMock() {
return new WireMock("my-pyroxy.corp", 8080);
}
}
I have noticed that after tests finish, the wiremock server receives a shutdown request. The Wiremock::shutdown method is not marked with any annotation like #PreDestroy but Spring is still invoking it.
How do I stop it (apart from creating this wiremock client bean outside of the spring context?)

From the documentation of #Bean, I have learned this
To disable destroy method inference for a particular #Bean, specify an empty string as the value, e.g. #Bean(destroyMethod="")

Related

Why does #Bean returning a mock work but #MockBean doesn't work when it comes to preserving Mockito state across threads in a spring boot test?

I have a JMS Spring Boot project, and I am trying to integration test with my JMS Listener, and I use mockito mocks to mock out beans with external service calls.
During testing, I was having an issue where Mockito.when / thenReturn returns a null within my JMS listener.
I was using #MockBean for the service in question, but when I used #Bean and return Mockito.mock, I was no longer getting a null value in my mock.
Does anyone know why there would be a difference between #MockBean defined like this
#MockBean
private Service myService;
and #Bean defined like this
#Bean
private Service myService(){
return Mockito.mock(Service.class);
}
when it comes to testing JMS Listeners? Please note that the spring test will be in thread[main], and the JMS listener will be listening on thread[DefaultMessageListenerContainer-1].
I figured out the issue with this. It turns out that Spring MockBean automatically resets after the test is completed. In the case of my JMS listener, it turns out that the main thread with the test has already completed and the mock has reset. For anyone else seeing the same behaviour, please validate that your main test thread has not completed yet.
Here is the code that I see in MockBean.java
/**
* The reset mode to apply to the mock bean. The default is {#link MockReset#AFTER}
* meaning that mocks are automatically reset after each test method is invoked.
* #return the reset mode
*/
MockReset reset() default MockReset.AFTER;

How to mock rest client inside a Spring boot integration test

In a spring boot integration test annotated with #SpringBootTest and ran with #RunWith(SpringRunner.class) I can drop real http post calls to my rest controller via #Autowired TestRestTemplate restTemplate and restTemplate.postForEntity(...)
This works fine, just at the end of the controller -> service -> restclient chain I have a rest client bean, which is calling a 3rd party rest endpoint using RestTemplates inside, so I have to mock this endpoint. I found this lib com.github.tomakehurst.wiremock.client.WireMock, which can be used for this, but was wondering whether there is not a nice spring boot way like for example the way to test a rest client with #RestClientTestto achieve this. I tried to mock the MockRestServiceServer so that I can write expectations and responses on it, but it does not seem to get it. The rest templates inside my rest client are always created as real, thus my call to the 3rd party endpoint fails.
You can inject the mock in the #Before using ReflectionTestUtils
#Inject
private Service service;
#Mock
private RestClient restClient;
#Before
public void setup() {
ReflectionTestUtils.setField(service, "restClient", restClient);
}

Spock with Spring Boot and Camel: Zero interactions with detached mock

I am having some issues with testing my camel context with spring boot.
I am using spring boot 1.5.6, spock 1.1-groovy-2.4, camel 2.19.2, and camel-spring-boot-starter 2.19.2.
I am using a spock mock, and I'm using the DetachedMockFactory in a #TestConfiguration class. All of my beans use constructor injection. I am injecting a mocked #Repository into one of the processor #Components, and I am also injecting it into my test class to define interactions.
I have my test annotated with #SpringBootTest with the classes list including all Processor implementations, and all RouteBuilder extensions. I also have an '#Import' with my TestConfiguration class. I am even using constructor injection for this repository bean in my test!
But it seems that the mock that is injected into the test class is not the one that is in use. Does anyone have an idea what could be wrong? I have tried #DirtiesContext to reload the context both before and after each test, but that did not help.
Problems with DetachedMocks not behaving correctly, e.g., appearing to be the same instance, are usually caused by some framework wrapping them in proxies. For example this can be caused by #Transactional annotation in Spring, which creates a proxy to facilitate jdbc-session management. See also issue #758
For spring you can use the methods of AopUtils (jdoc). The simple way is to use AopUtils.isAopProxy to check if it is proxied by spring an then unwrap it.
public static <T> T getTargetObject(Object proxy) throws Exception {
if (AopUtils.isAopProxy(proxy)) {
return (T) ((Advised) proxy).getTargetSource().getTarget();
} else {
return (T) proxy;
}
}
And in a Test
def "sample service test"() {
given:
def sampleRepositryMock = getTargetObject(sampleRepositry)
when:
sampleService.doSomething() // simply invoke sampleRepositry.doSomething() in it
then:
1 * sampleRepositryMock.doSomething()
0 * _
}
Edit: Since Spock 1.2 there is an extension to automatically unwrap injected beans #UnwrapAopProxy.
#Inject
#UnwrapAopProxy
SampleRepositry sampleRepositryMock
If someone comes up with the same problem.
Spock added additional #UnwrapAopProxy that will do the job for you instead of the util method mentioned above. You can also drop the DetachedMockFactory
#SpringSpy
#UnwrapAopProxy
Service service

Spring tries to autowire Mockito mocks

I have a spring managed application in which I like for my service layer to be mocked. So I created a Spring Application Java Config and returned a mock of the actual service.
For e.g,
#Bean
#Profile("resource")
public MyService mockService() {
return mock(MyService.class)
}
And then the MyService goes as
class MyService {
#Autowired
private MyDao dao;
}
When Spring creates bean of name "mockService", it also tries to Autowire MyDao on the mock ? This in my opinion defeats the purpose of mocking. Is this the expected behaviour, whats the workaround ?
So bottomline, its best practice to code to interfaces rather than concrete classes particularly if you are wanting to write focused tests on specific layers.
Well, I suppose you're trying to execute an integration test, but using some mocks, doing something like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = {Application.class, YourMockConfigurationClass.class})
#WebIntegrationTest
public class MyIntegrationTest {
...
}
In this case, you can create a mock of your service, and tell spring that this service instance has priority:
#Bean
#Primary
public MyService mockService() {
return mock(MyService.class)
}
Doing this, whenever Spring has to inject an unqualified MyService instance, it always chooses your mock. But it doesn't prevent Spring to create the original service.
So inside Spring context there will be two instances of MyService, the mock instance and the original implementation. But using #Primary you're telling Spring that your mock has priority.
On the other hand, in order to prevent Spring to load any mock in your environments (dev, test, etc...), you should annotate your mock configuration class either with a testing #Profile or a custom annotation (like #MockBean) and then configure your component scan strategy to not load this class (#ComponentScan(excludeFilters=#Filter(MockBean.class)))

Spring Bean Container

I wanted to write test cased for testing my service using springjunit runner.
My service will call another service and transform its out put and send the response.
I thouhgt that server need to be up and running for calling the other service while running junit.
But I was told that spring junit doesnt need server to be running.
Spring container will do the magic it seems.
Am not pretty sure how this happens.
Can any one enlighten me with how spring container can act as server?
If its so silly quesiton,sorry for that.Thanks in advance
do you need server to run java.class , answer is no, untill unless if you have any ejb component to be called from your service, or you service need some external web service to
respond (here you may need to either mock this service to give mock data or run the service on server)
i have service which calls data access layer , sometimes service calls another service.
all you need to have spring context configuration in your test class
#ContextConfiguration({ "classpath:spring-context.xml", "classpath:otherservice-context.xml"})
#RunWith(SpringJUnit4ClassRunner.class)
#Component
public class TestJuint{
#Autowire
private otherService otherServiceImpl;
#Autowire
private service serviceImpl;
#Test
public void testDummy{
serviceImpl.addDummy(dummyObj);
}
}
suppose if you need to have another service from some other package then you might want to include its context file in context configuration, so that its bean reference will be in spring context while autowiring

Resources