Kotlin,Spring 书,Mockito,@InjectMocks,使用与创建的模拟不同的模拟
Kotlin, Spring book, Mockito, @InjectMocks, Using different mocks than the ones created
我正在尝试测试 class 喜欢
@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 会使用测试 class 中的模拟,但这似乎不是真的。我如何获得@InjectMocks 使用的 JDBCRepo 实例?
看起来您想要 运行 使用所有 bean 进行完整的 spring 启动测试,但在应用程序上下文中您想要“模拟”一些真正的 beans 并提供您的自己的(mock-y)实现。
如果是这样,这里@Mock
的用法是错误的。 @Mock
和spring没有关系,纯粹是mockito的东西。它确实可以为您创建一个模拟,但它不会在 spring 启动的应用程序上下文中用这个模拟实现“替代”真正的实现。
为此,请改用 @MockBean
注释。这是来自spring“宇宙”的东西,它确实在幕后创建了一个 mockito 驱动的模拟,但在应用程序上下文中替换了常规 bean(或者如果真正的 bean 没有,甚至只是将这个模拟实现添加到应用程序上下文中) '甚至存在)。
要考虑的另一件事是如何获得 TotalCalculator
bean(尽管您不会在问题中直接问这个)。
TotalCalculator
本身可能是一个 spring 是 spring 引导为你创建的,所以如果你想 运行 一个“完整的”测试你应该从应用程序上下文中获取这个 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 的完整微服务并进行“集成”测试,那么这一切都是正确的
如果您只是想检查计算器的代码,这可能有点矫枉过正,您最终可以使用 mockito 和普通的旧单元测试。但是在这种情况下,您甚至不需要在测试期间启动 spring(读取创建应用程序上下文),当然也不需要使用 @SpringBootTest
/ @MockBean
/ @Autowired
.
所以这在很大程度上取决于这里真正需要什么样的测试
我正在尝试测试 class 喜欢
@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 会使用测试 class 中的模拟,但这似乎不是真的。我如何获得@InjectMocks 使用的 JDBCRepo 实例?
看起来您想要 运行 使用所有 bean 进行完整的 spring 启动测试,但在应用程序上下文中您想要“模拟”一些真正的 beans 并提供您的自己的(mock-y)实现。
如果是这样,这里@Mock
的用法是错误的。 @Mock
和spring没有关系,纯粹是mockito的东西。它确实可以为您创建一个模拟,但它不会在 spring 启动的应用程序上下文中用这个模拟实现“替代”真正的实现。
为此,请改用 @MockBean
注释。这是来自spring“宇宙”的东西,它确实在幕后创建了一个 mockito 驱动的模拟,但在应用程序上下文中替换了常规 bean(或者如果真正的 bean 没有,甚至只是将这个模拟实现添加到应用程序上下文中) '甚至存在)。
要考虑的另一件事是如何获得 TotalCalculator
bean(尽管您不会在问题中直接问这个)。
TotalCalculator
本身可能是一个 spring 是 spring 引导为你创建的,所以如果你想 运行 一个“完整的”测试你应该从应用程序上下文中获取这个 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 的完整微服务并进行“集成”测试,那么这一切都是正确的
如果您只是想检查计算器的代码,这可能有点矫枉过正,您最终可以使用 mockito 和普通的旧单元测试。但是在这种情况下,您甚至不需要在测试期间启动 spring(读取创建应用程序上下文),当然也不需要使用 @SpringBootTest
/ @MockBean
/ @Autowired
.
所以这在很大程度上取决于这里真正需要什么样的测试