How to write test class with #Autowired variable for inherited class - spring

I have problem with writing test cases using SPOCK. Could anyone please help me?
I have classes & interfaces like below,
//Helper class
public class ObjClass{
//Defining all property variables & corresponding getters & setters methods.
}
//Interface
public interface B{
//Declaring custom methods for Mongo repository.
public int getId();
}
public interface A extends MongoRepository<ObjClass, Serializable>, B{
//Defining some standard MongoRepository methods here
}
// Implementation Classes
public class Aimpl implements B{
//implementing all B interface methods
}
public class ctrlClass{
#Autowired
A aObj;
public int getIdValue(){
return aObj.getId();
}
}
And below is the corresponding SPOCK test cases:
class test extends Specification
{
ctrlClass obj1
A obj2 //interface class object
def setup(){
obj1 = new ctrlClass();
obj2 = new Aimpl(); //Creating object for interface using impl class.
obj1.aObj = obj2
}
def "test"(){
when:
def a = obj2.getIdValue()
then:
//validating some conditions here with 'a' value
}
}
Getting below error while executing above test case,
Cannot cast object Aimpl to class A.
The same above scenario is working fine with Spring #Autowired. But not in Spock.
*
Is there any alternate available for #Autowired in SPOCK? Please suggest me some solutions & your comments.
*

The problem you have is the ability of Spring to bind the interface with the related implementation.
If your interface has only one implementation and the single implementation has the annotation #Component with Spring's component scan enabled, than Spring framework success to infer the relationship between the interface and its implementation.
In case the component scan is not enabled, then the bean should be explicitly defined in your spring configuration file (such as application-config.xml).
The casting of Aimpl and A cannot succeed because the inheritance classes/interface are different.
You should change the code like the following:
public class ctrlClass{
#Autowired
Aimpl aObj;
public int getIdValue(){
return aObj.getId();
}
}
And in the test class make the following change:
A obj2 //interface class object
Should be changed to:
Aimpl obj2

Related

Generic type reverse lookup with Spring Boot #Service autowirings

Spring Boot & Java 11 here. I have an abstract base class:
public abstract class AbstractBurninator {
// ...
}
And some subclasses, such as:
public class FizzBurninator extends AbstractBurninator {}
public class BuzzBurninator extends AbstractBurninator {}
public class FoobazBurninator extends AbstractBurninator {}
But there are many more subclasses of it besides those three. I also have an interface:
public interface DoesThings<B extends AbstractBurninator> {
void doAllTheThings(B burninator, String payload);
}
So each implementation of the interface must specify the AbstractBurninator subclass it operates on. Hence I have:
public class DoesFizzThings implements DoesThings<FizzBurninator> {}
public class DoesBuzzThings implements DoesThings<BuzzBurninator> {}
public class DoesFoobazThings imlpements DoesThings<FoobazBurninator> {}
etc.
I now have a Spring Boot service (annotated with #Service) that gets autowired with a list of all List<DoesThings>. Inside that service I have a method that will infer (from certain logic) and instantiate an AbstractBurninator subclass, and it then needs to look up the DoesThings implementation associated with it. Hence if it infers an instance of FizzBurninator, I want it to select the DoesFizzThings instance from the autowired list:
#Service
public class BurninationService {
#Autowired
private List<DoesThings> thingDoers;
public void hahaha(Whistlefeather wf) {
// use 'wf' and other stateful data to infer a subclassed instance of 'AbstractBurninator':
AbstractBurninator burninator = inferSomehow();
// TODO: how to figure out which item of 'thingDoers' matches 'burninator'?
}
What's an easy and elegant way of doing this TBD lookup? I could inject a map instead:
private Map<AbstractBurninator,DoesThings> thingDoers;
But that seems unnecessary since each DoesThing has 1-and-only-1 corresponding AbstractBurninator. Any ideas? It's possible this can be done with straight Java generics, but I'm guessing Spring has some nifty utility that can help here.
If you are comfortable with wiring your Spring context into your service, you could do something like this (inspired by this SO accepted answer)
private <T extends AbstractBurninator> DoesThings<T> getSomeBurn(Class<T> clazz) {
String[] arr = ctx.getBeanNamesForType(ResolvableType.forClassWithGenerics(DoesThings.class, clazz));
if (arr.length == 1) {
return (DoesThings<T>) ctx.getBean(arr[0]);
} else {
throw new IllegalArgumentException("No burninator found");
}
}
This comes with a beautiful "unchecked cast" warning. Also, in my experience, wiring the application context indicates a design problem and definitely complicates testing.

How to determine the effective class (Bean) to be used when using an interface as a class member using Spring Boot?

Is it possible to achieve the following?
I want to determine the type of a class to be used at runtime with Spring Boot. Hence, I defined an interface MyInterface defining the required methods:
public interface MyInterface<C extends DocumentContext> {
MyResult<C> doForX(C documentContext);
MyResult<C> doForY(C documentContext);
}
An abstract base class implements this interface and provide some common methods:
#Slf4j
#Component
public abstract class BaseClass<C extends DocumentContext> implements MyInterface<C> {
private MyInterface myInterface;
...
public MyResult<C> doForX(C documentContext) { ... }
public Myresult<C> doForY(C documentContext) { ... }
}
This base class is the parent for two subclasses:
#RequiredArgsConstructor
#Slf4j
#Component
#ConditionalOnProperty(name = "sanitizerType", havingValue = "REGEX", matchIfMissing = false)
public class FirstClass<C extends documentContext> extends BaseClass<C> implements<MyInterface<C> {
...override base methods
}
#RequiredArgsConstructor
#Slf4j
#Component
#ConditionalOnProperty(name = "sanitizerType", havingValue = "SAX", matchIfMissing = false)
public class SecondClass<C extends documentContext> extends BaseClass<C> implements<MyInterface<C> {
...override base methods
}
A class using one of the two concrete subclasses:
public class MyUsingClass extends AnotherClass {
public MyUsingclass(MyInterface<ADocumentContext> myInterfaceImpl, ...)
...
}
This compiles but when I try to run the application I get:
*************************** APPLICATION FAILED TO START
Description:
Parameter 1 of constructor in MyUsingClass required a bean of type
'MyInterface' that could not be found.
Action:
Consider defining a bean of type 'MyInterface' in your configuration.
In my application.properties I have:
# ... [SAX | REGEX]
#sanitizerType=REGEX
...and I have a Properties class:
#Value("${sanitizerType:REGEX}")
private SanitizerType sanitizerType;
, whereby SanitizerType is just:
public enum SanitizerType {
REGEX, SAX
}
You said you would like to "determine the type of a class to be used at runtime with Spring Boot".
I'm not sure if you want your "class to be used" change while your application is running depending on current condidionts or set once when the application boots and use it always until the app is running.
If you uncomment this line of your application.properties #sanitizerType=REGEX
Your code should work - but it simply defines the SanitizerType (hence your MyInterface implementation) once when you start your application.
Please note that by setting a private field of Properties class you don't set the property globally (at least not the way you showed in the question), but only set the private field value either according what's set in your properties file or (if value is missing in properties) to "REGEX".
If you want to use it in different places of your program you need to inject it differently

Is there a way for #SpyBean to create spies for all types based on the interface type in a Spring Boot test?

I have a Spring Boot application where I would like to ensure that a list of decorators are verified to be executed. These decorators all extend from the same Abstract class, which in turn extend from the same interface, and they are autowired into a service class as a list of decorators. I would have thought that providing the #SpyBean(MyDecorator.class) at the class level of the test would have done the trick, but I got the error specifying that the decorator is not a spy. It looks like the MockitoPostProcessor class expects that we provide the individual concrete classes in the annotation as so #SpyBean(classes = {decorator1.class,decorator2.class}). I tried the latter, and it worked.
However, the issue that I have with this is that we have to add to this list every time we create a new decorator, which is not ideal. This is why I thought it makes sense to have the interface type be checked as well. Please let me know if there is a better way of doing this, or if I missed something. A thought that crossed my mind was to define my own post processor to wrap any bean from a defined type in a mockito spy, but I would like to check here first. Here is a skeleton definition of the classes to help you understand my dilemma.
MyDecorator.java
public interface MyDecorator{
public void decorate(SomeObject obj);
}
AbstractDecorator.java
public class AbstractDecorator implements MyDecorator{
//common decorator logic
}
Decorator1.java
#Component
public class Decorator1 extends AbstractDecorator{
public void decorate(SomeObject obj){
//decoration logic
}
}
Decorator2.java
#Component
public class Decorator2 extends AbstractDecorator{
public void decorate(SomeObject obj){
//decoration logic
}
}
DecorationService.java
#Service
public class DecorationService implements Service{
#Autowired
private List<MyDecorator> decoratorList;
public void processDecorators(){
//go through list of decorators and process some object
}
}
DecoratorServiceTest.java
#Runwith(SpringRunner.class)
#SpringBootTest
#ActiveProfiles("test")
//#SpyBean(MyDecorator.class) //<-- This doesn't wrap the classes in a spy and errors out
#SpyBean(classes = {Decorator1.class, Decorator2.class}) //<-- This works
public class DecoratorServiceTest{
#Autowired
private List<MyDecorator> decoratorList;
#Test
public void testProcessDecorator(){
//verify that each decorator was processed
}
}
I posted a spring boot github issue here. Hopefully we would either see an improvement on it or we get an explanation as to why it is designed in this way.
I have a workaround in place that I'm using which is I've created a class that implements Spring's BeanPostProcessor interface, and I override the postProcessAfterInitialization method, and I check if the class is what I'm expecting, then I would wrap it in a mockito spy. Also, you would need to define the spring bean.
Here is a snippet of the class that I created.
public class SpyBeanPostProcessor<T> implements BeanPostProcessor{
/**
* The class type to spy on.
*/
private Class<T> typeToSpy;
/**
* Construct a SpyBeanPostProcessor with a class type to wrap
* as a {#link org.mockito.Spy}
* #param typeToSpy The class type to spy on.
*/
public SpyBeanPostProcessor(Class<T> typeToSpy) {
this.typeToSpy = typeToSpy;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (typeToSpy.isAssignableFrom(bean.getClass())){
return Mockito.spy(bean);
}else{
return bean;
}
}
}
I also needed to create a new spring bean that loads the BeanPostProcessor as shown below.
#Bean
public static SpyBeanPostProcessor decoratorSpyBeanPostProcessor(){
return new SpyBeanPostProcessor(MyDecorator.class);
}

Spring Security and super class

fIn my app I'm using the Spring Security and have defined next classes.
public abstract class AbstractService {
public void save(){
.....
}
}
#Service
#PreAuthorize(SpelAuthorityExpressions.SOME_KIND_OF_ACCESS)
publist class UserService extends AbstractService {
}
#Service
#PreAuthorize(SpelAuthorityExpressions.SOME_KIND_OF_ACCESS_X)
publist class XService extends AbstractService{
}
I need #PreAuthorize annotation from the child class to be applied to the super class methods( for example: save()).Is there any way to achieve it by avoiding to override super class methods?
AbstractService will have more than one child( > 10) wherein each have own #PreAuthorize value.
You can try to use SPEL for that.
Because AFAIK, you must annotate methods or the superclass or the superclass itself, and the annotation must be a plain string (or a static final which is the same). But the string may contain SPEL expressions that will reference the target object. Example if only roles were used :
#PreAuthorize("hasAnyRole(#root.target.requiredRoles)")
public abstract class AbstractService {
public abstract String getRequiredRoles();
public void save(){
.....
}
}
#Service
#PreAuthorize(SpelAuthorityExpressions.SOME_KIND_OF_ACCESS)
publix class UserService extends AbstractService {
#Override
public String getRequiredRoles() {
return "ROLE_USER, ROLE_CLIENT";
}
....
}
As the condition is evaluated by SPEL at runtime, it will use the overriden getter and the list of roles can be defined in child class.
Without knowing what are your requirements for authorization expressions, I cannot be sure if that will do the trick, but I successfully use that for caching methods in a superclass, with keys depending on values in child classes.

spring 3 autowiring and junit testing

My code:
#Component
public class A {
#Autowired
private B b;
public void method() {}
}
public interface X {...}
#Component
public class B implements X {
...
}
I want to test in isolation class A. Do I have to mock class B? If yes, how? Because it is autowired and there is no setter where i could send the mocked object.
I want to test in isolation class A.
You should absolutely mock B, rather than instantiate and inject an instance of B. The point is to test A whether or not B works, so you should not allow a potentially broken B interfere with the testing of A.
That said, I highly recommend Mockito. As mocking frameworks go, it is extremely easy to use. You would write something like the following:
#Test
public void testA() {
A a = new A();
B b = Mockito.mock(B.class); // create a mock of B
Mockito.when(b.getMeaningOfLife()).thenReturn(42); // define mocked behavior of b
ReflectionTestUtils.setField(a, "b", b); // inject b into the B attribute of A
a.method();
// call whatever asserts you need here
}
Here's an example of how I got my tests working with Spring 3.1, JUnit 4.7, and Mockito 1.9:
FooService.java
public class FooService {
#Autowired private FooDAO fooDAO;
public Foo find(Long id) {
return fooDAO.findById(id);
}
}
FooDAO.java
public class FooDAO {
public Foo findById(Long id) {
/* implementation */
}
}
FooServiceTest.java
#RunWith(MockitoJUnitRunner.class)
public class FooServiceTest {
#Mock private FooDAO mockFooDAO;
#InjectMocks private FooService fooService = new FooService();
#Test public final void findAll() {
Foo foo = new Foo(1L);
when(mockFooDAO.findById(foo.getId()).thenReturn(foo);
Foo found = fooService.findById(foo.getId());
assertEquals(foo, found);
}
}
You can inject the field via reflection using Spring's ReflectionTestUtils.setField (or the junit extension PrivateAccessor) or you can create a mock application context and load that. Though for a simple unit (non-integration) test, I favor using reflection for simplicity.
This forum discussion makes sense to me. You can declare your private member b as a type of InterfaceB which is implemented by the class B (ie: service-oriented) then declare a MockB class would also implement the same interface. In your test environment application context, you declare MockB class and your production application context you declare the normal B class and in either case, the code for class A does not need to be changed since it will be auto-wired.

Resources