Подтвердить что ты не робот

Как можно проверить метод частного класса в Scala?

У меня есть объект-компаньон с частным методом, например:

package com.example.people

class Person(val age: Int)

object Person {
  private def transform(p: Person): Person = new Person(p.age + 1)
}

Я хотел бы протестировать этот метод с чем-то вроде:

class PersonSpec extends FlatSpec {

  "A Person" should "transform correctly" in {
    val p1 = new Person(1)
    val p2 = Person.transform(p1) // doesn't compile, because transform is private!
    assert( p2 === new Person(2) )
  }

}

Любая помощь при использовании тестового кода для частных методов?

Собственно, поскольку он написан, я мог бы создать подкласс Person, но что, если Person объявлен как final или sealed?

Спасибо!

4b9b3361

Ответ 1

Необходимость единичного тестирования частных методов - это запах дизайна.

Либо вы проверяете их через свой общедоступный API, который в порядке, если они являются небольшими и просто вспомогательными методами, или, что более вероятно, он содержит различные логические/ответственные обязанности и должен быть перенесен в другой класс, который используется делегацией в Человек. Затем вы сначала проверите публичный API этого класса.

Подробнее см. ответ.

Вероятно, вы можете получить к нему доступ, используя отражение Java/ Scala, но это всего лишь обходной путь для проблемы с дизайном. Тем не менее, если вам нужно, см. ответ на Java, как это сделать.

Ответ 2

Я посередине, когда дело доходит до тестирования всего. Обычно я не тестирую все, но иногда очень полезно иметь возможность unit test закрывать функцию, не сводя на нет мой код, чтобы сделать это возможным. Если вы используете ScalaTest, вы можете использовать программу PrivateMethodTester для этого.

import org.scalatest.{ FlatSpec, PrivateMethodTester }

class PersonSpec extends FlatSpec with PrivateMethodTester {

  "A Person" should "transform correctly" in {
      val p1 = new Person(1)
      val transform = PrivateMethod[Person]('transform)
      assert(p2 === invokePrivate transform(p1))
    }
  }

Это может быть не совсем то, что вы хотите сделать, но вы получите эту идею.

Ответ 3

Вы можете объявить свой метод приватным для пакета:

private[people] def transform(p: Person): Person = new Person(p.age + 1)

Если вы поместите PersonSpec в тот же пакет, он сможет получить к нему доступ.

Я оставляю это вам, чтобы решить, действительно ли это разумно для unit test частного метода:)

Ответ 4

Вообще говоря: если вы хотите эффективно протестировать свой код, вам first нужно написать его testable.

Scala реализует функциональную парадигму и широко использует неизменяемые объекты по дизайну, "примеры классов" являются примерами (мое мнение: класс Person должен быть классом case).

Реализация частных методов имеет смысл, если объекты имеют изменяемое состояние, в этом случае вы можете защитить состояние объектов. Но если объекты неизменны, зачем применять методы как частные? В вашем примере метод создает копию Person, по какой причине вы хотите сделать ее частной? Я не вижу причин.

Я предлагаю вам подумать об этом. Опять же, если вы хотите эффективно протестировать свой код, вам нужно его проверить.

Ответ 5

возможная работа будет проверять частный метод косвенно: тестирование общедоступного метода, который вызывает частный метод

Ответ 6

@jlegler answer здесь помог мне, но у меня все еще была отладка, прежде чем все работало, поэтому я подумал, что напишу именно то, что нужно для этого здесь.

для проверки:

class A

object A {
  private def foo(c: C): B = {...}
}

использование:

val theFuncion = PrivateMethod[B]('foo)
val result = A invokePrivate theFunction(c)

Обратите внимание на расположение A, B

Ответ 7

Я не думаю, что модульное тестирование касается контракта на тестирование класса - это тестирование простой функциональности (единицы).

Также я не думаю, что это хорошая идея, чтобы сделать некоторые методы общедоступными только для того, чтобы сделать их легко проверяемыми. Я считаю, что сохранение API настолько узким, насколько это возможно, это хороший способ помочь другим разработчикам использовать ваш код (IDE не будет предлагать частные методы) и понимать контракт.

Также мы не должны ставить все в один метод. Поэтому иногда мы можем поместить некоторую логику в частный метод... и, конечно же, мы хотим проверить ее также. Тестирование его через публичный API повысит сложность теста. (Другой вариант - переместить логику частного метода в другой класс-помощник и протестировать его там. Этот класс не будет использоваться непосредственно разработчиками и не будет загромождать api)

Ребята из scalatest, я думаю, добавили PrivateMethodTester для этой цели.

Ответ 8

Лично я говорю сделать все общедоступным и просто добавить _ или __, чтобы указать, что другие разработчики не должны его использовать.

Я понимаю, что это Scala, а не Python, но независимо, "Мы все соглашаем взрослых здесь" .

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