Mockito when/then not working - spring

I'm trying to Mock ValidatorService in unit tests of SubscriptionInterceptor.
validator = Mockito.mock(ValidatorService.class);
Mockito.when(validator.validateSubscription(any(), any(), any())).thenReturn("");
interceptor = new SubscriptionInterceptor(validator);
Later, when the interceptor calls the validateSubscription method of the mocked validator, an instance of the actual class is invoked, rather than the mock. Why? How can I get the method call to return an empty String?

Resolved in comments:
Method was declared final.
Mockito works by providing a proxy (subclass) of the class in question, with each of the methods overridden. However, for final classes and methods, Java assumes that it can detect which implementation it needs to call, and skips the dynamic method lookup. Because of this, Mockito cannot override behavior for final methods, static methods, or methods on final classes, and because you're not interacting with the mock Mockito cannot even warn you about it.
This is a very common problem; be sure to check for final fields if Mockito is not working for stubbing/verifying your method.

In order not to remove final, static fields/classes/methods in main java sources you could put mocks initialization after mockito's "when/then" stubs.
It will call a constructor for the mock object with finals after all stubs initialization.
Try:
Mockito.when(validator.validateSubscription(any(), any(), any())).thenReturn("");
validator = Mockito.mock(ValidatorService.class);
interceptor = new SubscriptionInterceptor(validator);

Related

#Autowired or private final

My question is simple. Which approach is more efficient?
method 1:
#Autowired
private CustomerRepository customerRepo;
method 2:
private final CustomerRepository custormerRepo;
public StudentService(CustomerRepository customerRepo) {
this.customerRepo = customerRepo;
}
As I see the DI in the method2 is more recent. But I wanted to ask you which one should I use?
TL;DR: Method 2 is much more flexible.
Method 1 is an example of field injection and method 2 is an example of constructor injection.
Field injection has some drawbacks that constructor injection avoids. Here are some advantages of constructor injection:
Immutability:
You can't do this is plain Java:
#Autowired
private final CustomerRepository customerRepo;
// No constructor that sets "customerRepo".
So, Spring offers constructor injection:
private final CustomerRepository customerRepo;
#Autowired
public StudentService(final CustomerRepository customerRepo) {
this.customerRepo = customerRepo;
}
Immutability is sometimes preferred. One reason is that it helps with thread-safety. Another is security.
Personally, I follow the rule, "if it can be final, it should be final."
Testing:
You won't need reflection to set the dependencies. Yes, many mocking frameworks handle this for you, but with constructor injection, you have the option to call new on the constructor.
Nasty NullPointerExceptions:
An object is created by calling its constructor, right? We usually want our arguments to be non-null at the time they are passed in. With constructor injection, the Spring IoC container makes sure that all the arguments passed in the constructor are available before passing them into the constructor.
use constructor injection, Spring also recommends it
In your main code, you should use method 2 as field injection (method 1) is not recommended. (see here for reasons)
In your test code, it's okay to use method 1.
I suggest you suggest something better. By using the Lombok library's #RequiredArgConstructor you are thus avoiding the boilerplate code. and if you wonder why #Autowired not reccomended , because of when you want to write unit testing in your application and there will be problem , where if you use #Autowired.
In addition to what the other answers have said about immutability, another benefit of constructor injection is to be able to avoid NPE is the field is not initialized. Using autowired, from a test, you’d create the class and then must remember to set the field. Using constructor injection, you can’t not initialize the field. This is more prominent in Kotlin where autowired fields are declared as lateinit var and throw a runtime exception if used before initialized. But a constructor argument can be declared as not null type which prevents you from even explicitly passing null.

Testing #Retryable and #Recover methods in Spring Boot + Mockito

For one class e.g. called Class A, I call an external api (with exceptions and I have mocked the class). In Class B, I have a method that calls Class A's method with the potential exceptions that could occur. Class B has the #Retryable and #Recover method. I have Class A as a mock object and Class B as a spy. When I mock Class A to throw an exception and I verify the times it has been called - I get the correct maxAttempts called. However, when I try to check and verify the method for recover or retryable I get:
UnfinishedVerificationException
..
Missing method call for verify....
Does anyone know if it is possible to verify these method calls?
Those methods can't be mocked because they they are final methods created by spring-retry using a CGLIB proxy.

Spring - disable Autoproxy for specific Bean

in order to mock some #Transactional annotated classes, I must disable Springs` aop proxy creation for them.
How can I configure my spring boot application to exclude any proxy creation for specific spring beans at all or how can I remove all advices for this bean?
Subclassing e.g. InfrastructureAdvisorAutoProxyCreator was already suggested, but throws an Class name [null] is not a known auto-proxy creator class error. It seems it's statically initialized in org.springframework.aop.config.AopConfigUtils.
Spring now offers a solution to this by providing AopTestUtils, e.g.
AopTestUtils.getUltimateTargetObject(bean)
My previous workaround unwrapped the proxy using Springs' AopUtils:
#SuppressWarnings("unchecked")
public <T> T unwrapProxy(T bean) {
if (AopUtils.isAopProxy(bean) && bean instanceof Advised) {
Advised advised = (Advised) bean;
try {
bean = (T) advised.getTargetSource().getTarget();
} catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}
return bean;
}
Not the answer to you original question. But I think you can use #InjectMocks of mockito as a solution here. It should work even if the class marked as #Transactional. Here are some questions on topic. From docs,
#InjectMock Mark a field on which injection should be performed.
Allows shorthand mock and spy injection.
Minimizes repetitive mock and spy injection.
Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as described below. If any of the following strategy fail, then Mockito won't report failure; i.e. you will have to provide dependencies yourself.
Constructor injection; the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only.
Note: If arguments can not be found, then null is passed. If non-mockable types are wanted, then constructor injection won't happen. In these cases, you will have to satisfy dependencies yourself.
Property setter injection; mocks will first be resolved by type, then, if there is several property of the same type, by the match of the property name and the mock name.
Note 1: If you have properties with the same type (or same erasure), it's better to name all #Mock annotated fields with the matching properties, otherwise Mockito might get confused and injection won't happen.
Note 2: If #InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.
Field injection; mocks will first be resolved by type, then, if there is several property of the same type, by the match of the field name and the mock name.
Note 1: If you have fields with the same type (or same erasure), it's better to name all #Mock annotated fields with the matching fields, otherwise Mockito might get confused and injection won't happen.
Note 2: If #InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.

How does Mockito #InjectMocks work?

Here's my question:
I have several web services classes to test that all inherit their methods from a generic service. Rather than write a unit test for each, I figure I can break the test suite down by functional areas (i.e. three groups of test methods, each relying on a different underlying DAO method call).
What I propose to do is:
#Mock StateDAO mockedStateDao;
#Mock CountyDAO mockedCountyDao;
#Mock VisitorDAO mockedVisitorDao;
then call:
#InjectMocks CountyServiceImpl<County> countyService = new CountyServiceImpl<County>();
#InjectMocks StateServiceImpl<State> stateService = new StateServiceImpl<State>();
#InjectMocks VisitorServiceImpl<Visitor> visitorService = new VisitorServiceImpl<Visitor>();
How can I be sure that each mockedDAO will be injected into the correct service?
Would it be easier to autowire all three (rather than use #InjectMocks)?
I'm using Spring, Hibernate, and Mockito...
Well nicholas answer is almost correct, but instead of guessing just look at the javadoc of InjectMocks, it contains more details ;)
To me it's weird to have so many Service in a single test, it doesn't feel right, as a unit test or as an integration test. In unit test it's wrong because well you have way too much collaborators, it doesn't look like object oriented (or SOLID). In integration tests, it's weird because the code you test the integration with the DB not mock it.
For a rapid reference in 1.9.5 you have :
Mark a field on which injection should be performed.
Allows shorthand mock and spy injection.
Minimizes repetitive mock and spy injection.
Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as described below. If any of the following strategy fail, then Mockito won't report failure; i.e. you will have to provide dependencies yourself.
Constructor injection; the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only.
Note: If arguments can not be found, then null is passed. If non-mockable types are wanted, then constructor injection won't happen. In these cases, you will have to satisfy dependencies yourself.
Property setter injection; mocks will first be resolved by type, then, if there is several property of the same type, by the match of the property name and the mock name.
Note 1: If you have properties with the same type (or same erasure), it's better to name all #Mock annotated fields with the matching properties, otherwise Mockito might get confused and injection won't happen.
Note 2: If #InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.
Field injection; mocks will first be resolved by type, then, if there is several property of the same type, by the match of the field name and the mock name.
Note 1: If you have fields with the same type (or same erasure), it's better to name all #Mock annotated fields with the matching fields, otherwise Mockito might get confused and injection won't happen.
Note 2: If #InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.
If you have multiple Services and would like to replace the DAOs with Mock-Objects in a Spring-based environment, I would recommend to use Springockito: https://bitbucket.org/kubek2k/springockito/wiki/Home
which is also mentioned here:
Injecting Mockito mocks into a Spring bean
Your Testclass then might look like this:
#RunWith (SpringJUnit4ClassRunner.class)
#ContextConfiguration (loader = SpringockitoContextLoader.class, locations = {"classpath:/org/example/package/applicationContext.xml"})
public class NameOfClassTest {
#Autowired
#ReplaceWithMock
StateDAO mockedStateDao;
#Autowired
#ReplaceWithMock
CountyDAO mockedCountyDao;
#Autowired
#ReplaceWithMock
VisitorDAO mockedVisitorDao;
In your #Test or #Before Methode you can setup your mocks the standard Mockito way:
Mockito.doReturn(null).when(mockedCountyDao).selectFromDB();
Well, the static method MockitoAnnotations.initMocks(Object) is used to bootstrap the whole process.
I don't know for sure how it works, as I haven't browsed the source code, but I would implement it something like this:
Scan the passed Object's class for member variables with the #Mock annotation.
For each one, create a mock of that class, and set it to that member.
Scan the passed Object's class for member variables with the #InjectMocks annotation.
Scan the class of each found member for members it has that can be injected with one of the mock objects created in (2) (that is, where the field is a parent class/interface, or the same class, as the mock objects declared class) and set it to that member.
Nevermind, looked online- the InjectMocks annotation treats anything with the #Mock annotation as a field and is static-scoped (class wide), so I really couldn't guarentee that the mocks would go to the correct service. this was somewhat a thought experiment for trying to unit test at feature level rather than class level. Guess I'll just autowire this stuff with Spring...

Calling AOPContext.currentProxy() from static method

I am using Spring's AOPContext.currentProxy() in a #service class implementation. However, i am using it in a static method and I do something like
public static void addCustomer() {
//....
((CustomerService) AopContext.currentProxy()).addCustomer();
//...
However, I am getting the error -- "cannot find proxy" set expose-proxy to true.
Is using static method the reason for this kind of error?
Note: "addCustomer" method is also static
Thanks in advance.
Proxy configuration is injected at the time of the instance creation. Suppose Using this proxy created instance you are calling to the method AOP is applicable to that method. Suppose without proxy instance or using class name ( in the case of static ) you are calling to the method it is direct call proxy config is not injected to the instance, So AOP is not applicable to that method call.
I'm not sure what you are trying to do, but you cannot do it this way at all.
Invocations of static methods are resolved at compile time, therefore they cannot be affected by proxy-based AOP. In other words:
AopContext.currentProxy() inside a static method doesn't make sense (unless you want to get a proxy for enclosing call of some instance method), because invocation of static method is not proxied
Calling a static method on an instance returned by AopContext.currentProxy() doesn't make sense, because it's resolved at compile time using a static type of expression, i.e. it compiles into CustomerService.addCustomer().
Does your configuration include something like <aop:config expose-proxy="true" />?

Resources