在春季进行自我注入,并使用Mockito测试

时间:2020-07-31 07:01:54

标签: java spring spring-boot junit mockito

我们正在使用Spring 5.2.x(带有Spring 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中是否还建议其他方法?
  2. Mockito绝对不能将自身bean注入CUT(被测类)的对象中。有没有办法以一种干净的方式实现这一目标?

我已经考虑了以下问题:

  1. self介绍一个setter,并使用它在设置方法中自我注入。不想只为测试添加设置器。
  2. 使用ReflectionUtils设置self。反射对我来说似乎是不干净的。我更喜欢@Setter
  3. 使用@RunWith(SpringJunit4Runner.class)进行了尝试,但是由于我未创建适当的上下文和内容而未能按预期进行。

1 个答案:

答案 0 :(得分:0)

在 setUp() 方法中调用 ReflectionTestUtils.setField(myClass, "self", myClass)