Модульный тест: имитация вложенного scala val

У меня есть два класса case А и AHelper

case class AHelper(data: String) {
  def getData() = {...} // Complex operation inside
}

case class A(data1: String, data2: String) {
  private val aHelper = AHelper(data2)    // AHelper instance
  def getData() = {data1 + aHelper.getData; ...} // Complex operation inside
}

класс А имеет экземпляр AHelper в качестве одного из своих членов.

Я хочу написать модульные тесты только для А, издеваясь над AHelper

Скала версия: 2.11

В реальном сценарии классы A и AHelper являются сложным кодом.

user811602 05.04.2019 09:25

почему вы не можете сделать простой класс? это будет легко

Raman Mishra 05.04.2019 09:59

@RamanMishra Помогает ли создание простого класса решить эту проблему?

user811602 05.04.2019 10:08

да, тогда вы можете переопределить getData и вернуть все, что хотите, просто в тестовом примере создайте новый объект A и переопределите getData. Поскольку в любом случае классы case используются для сопоставления с образцом, мы должны избегать функции данных внутри класса case.

Raman Mishra 05.04.2019 10:09

Я не хочу переопределять a.getData. Я хочу переопределить aHelper.getData. a.getData в реальном случае делает намного больше

user811602 05.04.2019 10:11

Я понял вашу точку зрения, но в конечном итоге вы собираетесь утверждать, что когда-либо возвращается A.getData? почему бы не переопределить его, и потому что в любом случае data1 будет доступен в объекте A, и если это невозможно сделать, сделайте AHelper простым классом

Raman Mishra 05.04.2019 10:14

во-первых, вам не нужен метод getData, вы можете просто получить параметры класса case, просто используя . Я имею в виду, что кажется, что Java использует scala.

Raman Mishra 05.04.2019 10:17

Вместо переопределения getData, почему бы не сделать val aHelper защищенным, а затем переопределить его в подклассе? Таким образом, вы можете использовать своего поддельного помощника, не изменяя никакую другую часть A.

Score_Under 05.04.2019 10:33
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
512
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Помощник должен быть параметром:

case class A(data1: String, data2: String)(aHelper: AHelper = AHelper(data2))

Теперь в ваших тестах вы можете делать: A("foo", "bar")(mock[AHelper])

Если вам не нравится второй список параметров, есть несколько вариантов:

Сделайте это неявным:

case class A(data1: String, data2: String)(implicit aHelper: AHelper = AHelper(data2))

Это позволяет создавать экземпляры только с помощью new A("foo", "bar") без необходимости засовывать () в конец.

Или создайте сопутствующий объект:

 object A {
   def apply(data1: String, data2: String): A = A(data1, data2)(AHelper(data2))
 }

Примечание также, что классы case с запутанной логикой, требующие модульных тестов,... необычны. Класс Case должен быть просто немым держателем данных, кортежем с именованными полями, если хотите. Вам следует подумать о том, чтобы разделить свою логику на эти классы или вместо этого сделать их "обычными" (без регистра) классами.

Например:

case class A1(data: String)
case class A2(data1: String, data2: A1)

trait AHelper {
  def getData(a1: A1)
}

class  AReader(helper: AHelper) {
  def getData(a: A2) = a.data1 + helper.getData(a.data2))
}

Теперь не возникает вопросов, как это правильно протестировать, правда?

спасибо за объяснение. Я новичок в скале. Дайте мне время, чтобы понять объект-компаньон и другую концепцию, и я вернусь, чтобы принять этот ответ.

user811602 12.04.2019 14:02

«кейс-классы с запутанной логикой, требующие модульных тестов… необычны», для меня это важное заявление. Это ваш опыт или общее правило?

user811602 16.04.2019 10:25

@user811602 user811602 и то, и другое :)

Dima 16.04.2019 22:07

Другие вопросы по теме