【问题标题】:Self injection in spring and testing it using mockito春季自我注入并使用mockito对其进行测试
【发布时间】:2020-11-21 00:37:42
【问题描述】:

我们正在使用 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,并用它在setup 方法中注入self。不想只为测试添加 setter。
  2. 使用ReflectionUtils 设置self。反射对我来说似乎不干净。我更喜欢@Setter。
  3. 尝试使用 @RunWith(SpringJunit4Runner.class),但由于我没有创建适当的上下文和内容,因此失败了。

【问题讨论】:

  • 这可能是将服务和 someTransactionalMethod() 重构为不同的类以便对其进行模拟的好案例吗?
  • someTransactionalMethod 在此服务中得到了很好的定义。仅用于测试,不要认为重构是个好主意。

标签: java spring spring-boot junit mockito


【解决方案1】:

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

【讨论】:

  • 我已经提到这不是我想要继续使用的方法。
猜你喜欢
  • 1970-01-01
  • 2012-09-12
  • 1970-01-01
  • 1970-01-01
  • 2019-07-12
  • 2016-03-03
  • 1970-01-01
  • 2017-12-13
  • 1970-01-01
相关资源
最近更新 更多