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 -
- 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?
- 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:
- Introduce a setter for
selfand use it to inject self in setup method. Don't want to add a setter only for tests. - Use
ReflectionUtilsto setself. Reflection seems unclean to me. I would prefer@Setterover this. - Tried using
@RunWith(SpringJunit4Runner.class)but that failed as expected because I am not creating a proper context and stuff.