我有一个看起来像这样的配置提取器。
def getForCountry[A](path: String, fallbackToDefault: Boolean)
(implicit loader: ConfigLoader[A], ac: AppContext): A = {
configuration.getOptional[A](s"${ac.country}.$path") match {
case Some(value) =>
value
case None if fallbackToDefault =>
configuration.get[A](path)
case None if !fallbackToDefault =>
throw new RuntimeException(s"${ac.country}.$path key not found in configuration")
}
调用相同的方法如下 -
val countrySpecificConfig =
configurationHelper.getForCountry[Map[String, String]]("googleCloudPlatform.jobConfig.demandBasedPricing", fallbackToDefault = false)
现在我想在单元测试中模拟getForCountry方法 -
when(configurationHelper
.getForCountry[Map[String, String]]("googleCloudPlatform.jobConfig.demandBasedPricing", fallbackToDefault = false))
.thenReturn(countryPricingWeekConfiguation)
令人惊讶的是,似乎没有正确设置这种期望。在执行测试时,mock返回null。
有关如何进行此操作的任何线索?如果您需要任何进一步的细节,请随时告诉我。
我强烈怀疑隐含的ConfigLoader
和AppContext
的不同实例是在实际的方法调用中传递并模拟了一个。如果您正在使用intellij,请通过启用它们来验证通过哪些implicits。要启用它们,请按ctr+alt+shift++
这是完整的测试模拟你的情况,工作得很好:
test("mock example") {
trait ConfigLoader[T] {}
trait AppContext { def country: String }
trait ConfigurationHelper {
def getForCountry[A](x: String, fallbackToDefault: Boolean = true)(implicit loader: ConfigLoader[A], ac: AppContext): A
}
implicit val loader: ConfigLoader[Map[String, String]] = mock[ConfigLoader[Map[String, String]]]
implicit val ctx: AppContext = mock[AppContext]
val configurationHelper = mock[ConfigurationHelper]
val mockedResult = Map("x" → "1")
when(
configurationHelper
.getForCountry[Map[String, String]]("googleCloudPlatform.jobConfig.demandBasedPricing", fallbackToDefault = false)
).thenReturn(mockedResult)
val countrySpecificConfig =
configurationHelper
.getForCountry[Map[String, String]]("googleCloudPlatform.jobConfig.demandBasedPricing", fallbackToDefault = false)
countrySpecificConfig.foreach(println)
}
// =========================== Output ====================
// (x,1)
非常感谢Pritam。以下代码似乎有效。
when(configurationHelper
.getForCountry[Map[String, String]]
(ArgumentMatchers.eq("googleCloudPlatform.jobConfig.demandBasedPricing"), ArgumentMatchers.eq(false))
(ArgumentMatchers.any[ConfigLoader[Map[String, String]]](), ArgumentMatchers.any[AppContext]()))
.thenReturn(countryPricingWeekConfiguation)
你试过mockito-scala吗?如果您使用新语法,将自动处理implicits(假设您使用惯用语法并在测试和prod代码中解析相同的实例)
即使您使用传统语法,您的存根也会减少到
when(configurationHelper
.getForCountry[Map[String, String]]
(eqTo("googleCloudPlatform.jobConfig.demandBasedPricing"), eqTo(false))(*, *)
.thenReturn(countryPricingWeekConfiguation)
或者用惯用语法
configurationHelper.getForCountry[Map[String, String]]
("googleCloudPlatform.jobConfig.demandBasedPricing",false)
shouldReturn countryPricingWeekConfiguation
或者如果测试和产品中的含义不一样(请注意我也可以混合使用像*和原始参数这样的'假'的arg匹配器)
configurationHelper.getForCountry[Map[String, String]]
("googleCloudPlatform.jobConfig.demandBasedPricing",false)(*,*)
shouldReturn countryPricingWeekConfiguation