У меня есть сборщик конфигураций, который выглядит примерно так.
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)
Удивительно, кажется, что это ожидание не настроено должным образом. При выполнении теста макет возвращает null.
Любые подсказки о том, как поступить с этим? Пожалуйста, не стесняйтесь, дайте мне знать, если вам нужна дополнительная информация.
Я сильно сомневаюсь, что разные экземпляры неявных ConfigLoader
и AppContext
передаются в вашем фактическом вызове метода и издеваются над ним.
Если вы используете intellij, проверьте, какие имплициты передаются, включив их. Чтобы включить их, нажмите 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)
Большое спасибо, Притам. Следующий код работает.
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)
Вы пробовали мокито-скала? если вы используете новый синтаксис, имплициты будут обрабатываться автоматически (при условии, что вы используете идиоматический синтаксис и одни и те же экземпляры разрешаются в тесте и в вашем производственном коде)
Кроме того, даже если вы используете традиционный синтаксис, ваша заглушка будет сокращена до
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
или если имплициты не совпадают в test и prod (обратите внимание, я также могу смешивать сопоставления аргументов, такие как *, и необработанные параметры, такие как «false»)
configurationHelper.getForCountry[Map[String, String]]
("googleCloudPlatform.jobConfig.demandBasedPricing",false)(*,*)
shouldReturn countryPricingWeekConfiguation