java - 使用 lombok @RequiredArgsConstructor(onConstructor = @__(@Autowired)) 时,Mockito when().thenReturn() 的行为不符合预期

标签 java spring mockito junit4 lombok

我有 Spring 类说

@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
class MainServiceImpl implements MainService {
    private final InternalService internalService;

    public Set<String> do(String anything) {
      Set<String> relevent = internalService.finaIntern(anything);
      return relevent;
    }
}

我正在编写如下单元测试用例

@RunWith(MockitoJUnitRunner.class)
class TestMainServiceImpl {

    @InjectMocks
    private MainServiceImpl service;

    @Mock
    InternalService internalService;   

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

    @Test
    public void testDo() { 
        Set<String> setData = new HashSet<>();
        setData.add("ABC");
        String a ="a";
        when(internalService.finaIntern(any(String.class))
                                  .thenReturn(setData);
        Set<String> result = service.do(a);
        assertTrue(!result.isEmpty());
    }

}

这里我的测试用例失败了,但是如果我删除 MainServiceImpl 中的 final 并执行如下所示的显式 @Autowired

@Component
class MainServiceImpl implements MainService {
    @Autowired
    private InternalService internalService;
     .....

我很想知道 1.如果我删除final关键字,我的测试用例如何通过 2. 使用 @RequiredArgsConstructor 是一个好的做法吗?如果是,那么如何使用,如果不是,那么为什么?

提前致谢

最佳答案

它与lombok和Spring@Autowired无关 @RunWith(MockitoJUnitRunner.class)MockitoAnnotations.initMocks(this); 的组合就是问题所在。删除其中任何一个,行为就会如预期。你不需要他们两个。事实上, MockitoAnnotations.initMocks(this); 仅在无法使用 @RunWith(MockitoJUnitRunner.class) 的情况下存在,例如,如果您需要使用 SpringRunner.class.

这就是它不起作用的原因。 首先,您的对象被实例化。因此,您的 @Mock 已创建并注入(inject)到您的 @InjectMock 对象中:

下面你可以看到,injectIntomock 内部新创建了模拟 (mocks[0])、service 是同一个对象。

enter image description here

但随后初始化会发生第二次。 因此,mockito 创建一个新的 @Mock 对象,并尝试将其注入(inject)到已经实例化的 @InjectMock 对象中。但最终未能将其注入(inject)现场。 这是第二次初始化后的结果:

enter image description here 正如您所看到的,现在 testClassInstance 中的模拟对象和注入(inject)到测试对象中的模拟对象是不同的。

@RequiredArgsConstructor怎么样:对我来说,按照你的方式使用它是完全可以的。

关于java - 使用 lombok @RequiredArgsConstructor(onConstructor = @__(@Autowired)) 时,Mockito when().thenReturn() 的行为不符合预期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44283137/

相关文章:

java - 将kafka-consumer设置为consumer-group中的容灾消费者?

java - 如何在 JSF 中获取绝对 url?

java - 在 Java 中同步共享静态对象的正确方法是什么?

android - 如何验证方法是否在模拟类的回调中运行?

android - 如何模拟 Kotlin 中的对象?

java - 将 REPL 添加到 Java 项目的技巧

java - Spring-Boot 2+ 强制使用 CGLIB 代理,即使 proxyTargetClass = false

java - 如何获取在 AWS Elastic Beanstalk 应用程序负载均衡器上运行的 Spring Web 应用程序上的请求者 IP

java - Websphere Portal 8.5 上的 CXF 依赖性错误

java - 如何使用 Mockito 测试不模拟对象的异步方法?