Self injection in spring and testing it using mockito

Viewed 1050

We are using Spring 5.2.x (with Spring Boot 2.3.x) & Mockito 3.3.x.

I need to call a @Transactional method in my service from within it. Hence I had to resort to self injection.

@Service
@RequiredArgsCostructor // lombok
public class MyClass {
    private final dep1;
    private final dep2;

    @Autowired
    private MyClass self;

    public void someMethod() {
        self.someTransactionalMethod();
        // do something
    }

    @Transactional
    public void someTransactionalMethod() {
        // do something
    }
}

public class MyClassTest {
    @Mock
    private dep1;
    
    @Mock
    private dep2;

    @InjectMocks
    private MyClass myClass;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void someMethodTest() {
        // NPE when calling self.someTransactionalMethod()
    }
}

From the code it is relevant that we are using constructor injection using lombok. For obvious reasons, I cannot declare the instance variable self as final, hence using @Autowired for this one. The class works fine but I see issues with the unit test.

There are 2 parts to my question -

  1. Regarding the way I am doing self injection - is this the best way of doing self injection? Is there any other approach recommended by the authors of Spring framework in recent versions of Spring?
  2. Mockito is by no means able to inject the self bean into the object of CUT (Class Under Test). Is there a way to achieve this in a clean way?

I have already considered the following:

  1. Introduce a setter for self and use it to inject self in setup method. Don't want to add a setter only for tests.
  2. Use ReflectionUtils to set self. Reflection seems unclean to me. I would prefer @Setter over this.
  3. Tried using @RunWith(SpringJunit4Runner.class) but that failed as expected because I am not creating a proper context and stuff.
1 Answers

In setUp() method call ReflectionTestUtils.setField(myClass, "self", myClass)

Related