Kotlin,Spring book,Mockito,@InjectMocks,使用与创建的不同的模拟
Posted
技术标签:
【中文标题】Kotlin,Spring book,Mockito,@InjectMocks,使用与创建的不同的模拟【英文标题】:Kotlin, Spring book, Mockito, @InjectMocks, Using different mocks than the ones created 【发布时间】:2022-01-13 02:56:46 【问题描述】:我正在尝试测试类似的课程
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@SpringBootTest(classes = [TestConfig::class])
@ExtendWith(MockitoExtension::class)
class TotalCalculatorTests
@Mock
lateinit var jdbcRepo: JDBCRepo
@Mock
lateinit var userCache : LoadingCache<ApproverLevel, List<Approver>>
@InjectMocks
lateinit var calculator: TotalCalculator
@Test
fun totalOrder()
// val calculator = TotalCalculator(userCache,jdbcRepo)
calculator.total(ItemA(),ItemB())
verify(jdbcRepo).getTotal()
我收到一个错误 Actually, there were zero interactions with this mock.
但如果我取消注释 // val calculator = TotalCalculator(userCache,jdbcRepo)
它可以工作。我假设 mockito 将使用来自测试类的模拟,但这似乎不是真的。如何获取 @InjectMocks 正在使用的 JDBCRepo 实例?
【问题讨论】:
【参考方案1】:看起来您希望使用所有 bean 运行成熟的 Spring Boot 测试,但在应用程序上下文中您希望“模拟”一些真正的 bean 并提供您自己的 (mock-y) 实现。
如果是这样,这里@Mock
的用法是错误的。 @Mock
与 spring 无关,它纯粹是模仿者的事情。它确实可以为您创建一个模拟,但它不会在 Spring Boot 的应用程序上下文中用这个模拟实现“替代”真正的实现。
为此,请改用@MockBean
注释。这是来自春天“宇宙”的东西,它确实在引擎盖下创建了一个 mockito 驱动的模拟,但在应用程序上下文中替换了常规 bean(或者如果真正的 bean 甚至不存在,甚至只是将此模拟实现添加到应用程序上下文中) )。
要考虑的另一件事是如何获得TotalCalculator
bean(尽管您没有直接在问题中提出这个问题)。
TotalCalculator
本身可能是 Spring Boot 为您创建的弹簧,因此如果您想运行“完整的”测试,您应该从应用程序上下文中获取此 bean 的实例,而不是创建一个自己举例。为此目的使用注释@Autowired
:
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@SpringBootTest(classes = [TestConfig::class])
@ExtendWith(MockitoExtension::class) // you don't need this
class TotalCalculatorTests
@MockBean
lateinit var jdbcRepo: JDBCRepo
@MockBean
lateinit var userCache : LoadingCache<ApproverLevel, List<Approver>>
@Autowired // injected by the spring test infrastructure
lateinit var calculator: TotalCalculator
@Test
fun totalOrder()
// val calculator = TotalCalculator(userCache,jdbcRepo)
calculator.total(ItemA(),ItemB())
verify(jdbcRepo).getTotal()
现在,如果您的目的确实是运行 Spring Boot 的完整微服务并进行“集成”测试,那么这一切都是正确的
如果你只是想检查你的计算器的代码,这可能是一个矫枉过正,你可以最终使用 mockito 和普通的旧单元测试。但是在这种情况下,您甚至不需要在测试期间启动 spring(读取创建应用程序上下文),当然也不需要使用 @SpringBootTest
/ @MockBean
/@Autowired
。
所以这在很大程度上取决于这里真正需要什么样的测试
【讨论】:
是的,我想要集成测试,非常感谢您的精彩回答!!!以上是关于Kotlin,Spring book,Mockito,@InjectMocks,使用与创建的不同的模拟的主要内容,如果未能解决你的问题,请参考以下文章
Spring Webflux: Kotlin DSL [片断]