我们使用的是Spring 5.2.x(带Sping Boot 2.3.x)和Mockito 3.3.x。
我需要在服务中调用一个@Transactional
方法,因此我不得不求助于自我注入。
@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()
}
}
从代码来看,我们使用lombok的构造函数注入是相关的。由于显而易见的原因,我不能将示例变量self
声明为final
,因此使用@Autowired
。类工作正常,但我发现单元测试有问题。
我的问题分为两部分-
1.关于我做自我注入的方式--这是做自我注入的最好方式吗?在Spring的最新版本中,Spring框架的作者还推荐了其他的方法吗?
- Mockito根本无法将self bean注入到CUT(Class Under Test)的对象中,有没有一种干净的方法可以做到这一点?
我已经考虑了以下几点:
1.为self
引入一个setter,并使用它在setup方法中注入self。不要只为测试添加setter。
1.使用ReflectionUtils
来设置self
。反射对我来说似乎不干净。我更喜欢@Setter
而不是这个。
1.尝试使用@RunWith(SpringJunit4Runner.class)
,但如预期的那样失败了,因为我没有创建适当的上下文和东西。
2条答案
按热度按时间cs7cruho1#
在setUp()方法中调用ReflectionTestUtils.setField(myClass,“自我”,myClass)
vpfxa7rd2#
如果插入自引用很困难或者你需要ReflectionTestUtils来完成它,这是因为测试不是一个纯单元测试,在你的情况下,这是因为服务没有一个定义好的接口。如果我们改变服务来实现一个接口,并将测试改为纯单元测试,代码将变成如下所示,问题也就消失了:
测试变成:
现在,
someMethod()
的测试遵循单元测试原则,实际上只测试someMethod()
中的代码,而不是将someTransactionalMethod()
包括在它的复杂性中。然后,您为someTransactionalMethod()
编写单独的单元测试,以确保它正常运行。