Mockito when(). thenreturn()总是返回null



我有以下服务:

@Service
@RequiredArgsConstructor
public class LimitService {
private final CoreService coreService;
private final AuditService audit;
public Limit get(User user) {
Limit limit = coreService.get(user);
if (limit != null) {
Optional.ofNullable(limit.getAvailable())
.map(String::valueOf)
.map(BigDecimal::new)
.map(availableValue -> availableValue.setScale(2, RoundingMode.HALF_DOWN))
.map(BigDecimal::doubleValue)
.ifPresentOrElse(val -> limit.setAvailable(val), () -> limit.setAvailable(0d));
}
return limit;
}
}

和以下相关测试

@ExtendWith(MockitoExtension.class)
public class LimitServiceTest {
@Mock
private CoreService coreService;
@Mock
private AuditService audit;
@InjectMocks
private LimitService service;
@BeforeEach
public void init(){
MockitoAnnotations.openMocks(this);
}

@Test
public void shouldReturnNull(){
assertThat(this.service.get(new User())).isNull();
}
@Test
public void shouldSetToZero_whenNull(){
User user = new User();
Mockito.when(this.coreService.get(any(User.class)))
.thenReturn(new Limit());
assertThat(this.service.get(user)).extracting(Limit::getAvailable)
.isEqualTo(0d);
}
}

当我在调试模式下运行第二个测试时,我可以看到实际上为CoreService生成了一个mock,但Mockito似乎忽略了When ..thenReturn.

我也尝试使用eq(user)而不是任何(user .class),但结果是一样的。我在另一个项目中进行了类似的测试,一切都很好。我不知道为什么在这种情况下不工作。

@ExtendWith(MockitoExtension.class)
public class LimitServiceTest {
@Mock
private CoreService coreService;
@Mock
private AuditService audit;
@InjectMocks
private LimitService service;
@BeforeEach
public void init(){
MockitoAnnotations.openMocks(this);
}
// ...

@InjectMocks首先运行(由MockitoExtension执行),并将模拟实例分配给带注释的LimitService字段中的字段。

稍后,openMocks创建第二组模拟实例,并将它们分配给测试中的字段(但不重新分配服务的字段)。服务仍然会引用由扩展创建的模拟实例。

这可以通过在调用openMocks之前和之后打印字段的身份哈希码来验证:

@BeforeEach
public void init(){
System.err.println("@InjectMocks:");
System.err.println(System.identityHashCode(coreService));
System.err.println(System.identityHashCode(service.coreService));
MockitoAnnotations.openMocks(this);
System.err.println("openMocks(this):");
System.err.println(System.identityHashCode(coreService));
System.err.println(System.identityHashCode(service.coreService));
}

(这需要暂时使LimitService#coreService字段可访问)。示例输出:

@InjectMocks:
763677574
763677574
openMocks(this):
234857227
763677574

调用when现在为第二个模拟实例设置存根,但是您的服务不知道这个实例,因为它只保存对第一个模拟实例的引用。

这个和相关的问题在"为什么我的类在单元测试中不调用我的模拟方法"的回答中讨论。

最新更新