Testing #Retryable and #Recover methods in Spring Boot + Mockito - spring-boot

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.

Related

Spring's BeanFactory getBean method returns JDK proxy when using #Async (with custom thread executor)

I am new to spring and trying to understand the framework. I have a class (say ClassA) which has execute() method. I am using "prototype" scope (#Scope) for this class.I am using #Async("customThreadPoolTaskExecutor) for this execute() method. I have already defined this customThreadPoolTaskExecutor in another class with #Configuration. Then I have another class (say ClassB) which uses BeanFactory of spring to get an object of ClassA using beanFactory.getBean(ClassA).
I am getting an error on this line inside ClassB
ClassA A = (ClassA) beanFactory.getBean(ClassA);
Error is as below
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'ClassA' is expected to be of type 'ClassA' but was actually of type 'jdk.proxy2.$Proxy103'
Note that above code works fine and returns an object of ClassA if I remove #Async from execute() method of ClassA.
I am looking to understand the root of the problem and clear some of my concepts about spring. What is the relationship between #Async and bean creation using BeanFactory's getBean method. Why does it work without #Async but not with #Async.
Note : The fix/workaround I have so far is to add "ScopedProxyMode" for ClassA as "TARGET_CLASS". After adding this to ClassA's #Scope annotation, things work ok but I am not able to understand the root cause of the issue.

Spring disable transactions for a single class method

In my Spring application, I have a class annotated with org.springframework.transaction.annotation.Transactional annotation.
Is it possible to discard transactions for a specific single method of this class without removing #Transactional from class level declarations? If so, please show an example
According to Transactional documentation:
public #interface Transactional
Describes a transaction attribute on an individual method or on a class.
So additionally to the class-level annotation just define the correct attribute at your method to disable the default transaction handling.
example:
#Transactional(propagation=Propagation.NEVER)
public long notInTransaction(AnythingData anythingData) throws Exception {
//JDBC code...
}
Will throw an exception if this method is called inside an active transaction. Whereas Propagation.NOT_SUPPORTED will "suspend" the current transaction and make sure that the method is called non transactional.

Mockito when/then not working

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);

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" />?

Spring - Proxying Behind the Scenes

What happens behind the scene when We Proxy a object. Say for example i say that a bean id = "bookService" refers to the class TransactionProxyFactoryBean of Spring.
The target attribute of the TransactionProxyFactoryBean points to BookServiceImpl class. So BookServiceImpl (Which is an implementation of the interface BookService) is getting proxied.
But what happens here? Does this TransactionProxyFacotoryBean Class extends the target that is getting proxied?
If so, will the TransactionProxyFactoryBean subtype itself from the BookServiceImpl (implementation) or the BookService (Interface)?
The TransactionProxyFactoryBean will create a proxy. It won't itself be a proxy.
This proxy will handle the calls to your bean and, for the methods that you have configured to have transactions applied, will call the TransactionInterceptor which will start the transaction, call your bean's method, then end the transaction.
If you have proxyTargetClass="true" then the proxy will be a subtype of the class (using CGLIB). Otherwise the proxy will be a subtype of the interface that the target class implements.

Resources