У меня есть два класса 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
почему вы не можете сделать простой класс? это будет легко
@RamanMishra Помогает ли создание простого класса решить эту проблему?
да, тогда вы можете переопределить getData и вернуть все, что хотите, просто в тестовом примере создайте новый объект A и переопределите getData. Поскольку в любом случае классы case используются для сопоставления с образцом, мы должны избегать функции данных внутри класса case.
Я не хочу переопределять a.getData. Я хочу переопределить aHelper.getData. a.getData в реальном случае делает намного больше
Я понял вашу точку зрения, но в конечном итоге вы собираетесь утверждать, что когда-либо возвращается A.getData? почему бы не переопределить его, и потому что в любом случае data1 будет доступен в объекте A, и если это невозможно сделать, сделайте AHelper простым классом
во-первых, вам не нужен метод getData, вы можете просто получить параметры класса case, просто используя . Я имею в виду, что кажется, что Java использует scala.
Вместо переопределения getData, почему бы не сделать val aHelper защищенным, а затем переопределить его в подклассе? Таким образом, вы можете использовать своего поддельного помощника, не изменяя никакую другую часть A.





Помощник должен быть параметром:
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 user811602 и то, и другое :)
В реальном сценарии классы A и AHelper являются сложным кодом.