【问题标题】:Clarification about @Spy and @InjectMocks inside a @Service Spring Boot关于@Service Spring Boot 中的@Spy 和@InjectMocks 的说明
【发布时间】:2019-04-26 07:41:17
【问题描述】:

嗯,我对@Spy 和@Mock 感到很困惑。据我了解,@Spy 会调用真正的方法而@Mock/@InjectMocks 不会,因为它只是一个模拟,如果我想改变模拟的行为,我需要一个存根(when.thenReturn)。

在我的测试课中,我有这个代码:

@RunWith(MockitoJUnitRunner.class)
public class CaixaServiceTest {

    @InjectMocks
    private CaixaService caixaService;

    @Mock
    private CaixaRepository caixaRepository;

所以,CaixaRepository 是 Spring Data 的 JpaRepository 接口,CaixaService 只是有一个非常简单的方法:

public void calcular(){
        int a = (int) Math.pow(1,3);
        log.info(a);
    }

如果我调用 caixaRepository.findOne(id) 应该返回 null ,因为 findOne 从未真正被调用过,因为它只是一个模拟。这个案例效果很好。

但是当我调用caixaService.calcular() 时,方法体被执行(不应该因为它是一个模拟),所以log.info(a) 记录在我的文件中。

我无法理解这种行为,因为正如我所说,如果存根不存在,@InjectMocks 或 @Mock 不应执行任何操作,这是一个 @Spy 任务。

【问题讨论】:

  • 服务不是模拟的。这是一个真实的对象,模拟由 Mockito 注入。如果一切都被模拟了,你可以测试任何一行代码。
  • 服务不是模拟,它被正确实例化,但它的成员充满了模拟
  • 所以 InjectMocks 像间谍一样工作?
  • 没有。 InjectMocks 简单地创建对象的真实实例,并注入模拟和间谍,这要归功于 Mock 和 Spy 注释。为什么不阅读 javadoc?

标签: java mockito


【解决方案1】:

一切正常,但您对@InjectMocks的理解。
实际上,用它注释字段不会像您想象的那样创建模拟对象。
相反,它将尝试将模拟依赖项注入到注释所在的字段所引用的对象中。
请注意,这种注入依赖项的方式并不明确,因此不会记录要在测试中模拟的依赖项。
此外,如果依赖注入失败,Mockito 不会报告任何失败。

【讨论】:

  • 注入模拟依赖项的最佳实践是什么?
  • @Mock注入它,没问题。但是我会在 @Before/@BeforeEach (JUnit 4 / 5) 方法中的构造函数调用中将它们设置在被测对象中,例如 foo = new Foo(barMock, otherBarMock);
  • 确实如此,这样我就遵循了面向对象的最佳实践。谢谢@davidxxx
  • 所以我应该删除 InjectMocks 并创建 "new CaixaService(mock1,mock2..)" 对吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-24
  • 2017-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多