Как мы можем смоделировать метод scala с универсальным типом возвращаемого значения и неявными параметрами? - PullRequest
0 голосов
/ 17 марта 2019

У меня есть сборщик конфигурации, который выглядит примерно так.

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)

Удивительно, но кажется, что это ожидание не настроено должным образом.При выполнении теста макет возвращает ноль.

Есть какие-нибудь подсказки, как это сделать?Пожалуйста, дайте мне знать, если вам нужна дополнительная информация.

Ответы [ 3 ]

1 голос
/ 17 марта 2019

Я сильно сомневаюсь, что различные экземпляры неявных 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)

0 голосов
/ 17 марта 2019

Вы пробовали mockito-scala ? если вы используете новый синтаксис, о последствиях позаботятся автоматически (при условии, что вы используете идиоматический синтаксис, и те же экземпляры разрешены в тесте и в вашем коде продукта)

Также, даже если вы используете традиционный синтаксис, ваша заглушка будет уменьшена до

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, такие как *, и необработанные параметры, такие как 'false')

configurationHelper.getForCountry[Map[String, String]]
    ("googleCloudPlatform.jobConfig.demandBasedPricing",false)(*,*)
    shouldReturn countryPricingWeekConfiguation
0 голосов
/ 17 марта 2019

Спасибо, тонна Притам.Следующий код, кажется, работает.

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)
...