我有 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
对象中:
下面你可以看到,injectInto
和 mock 内部新创建了模拟 (
是同一个对象。mocks[0]
)、service
但随后初始化会发生第二次。
因此,mockito 创建一个新的 @Mock
对象,并尝试将其注入(inject)到已经实例化的 @InjectMock
对象中。但最终未能将其注入(inject)现场。
这是第二次初始化后的结果:
正如您所看到的,现在 testClassInstance
中的模拟对象和注入(inject)到测试对象中的模拟对象是不同的。
@RequiredArgsConstructor
怎么样:对我来说,按照你的方式使用它是完全可以的。
关于java - 使用 lombok @RequiredArgsConstructor(onConstructor = @__(@Autowired)) 时,Mockito when().thenReturn() 的行为不符合预期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44283137/