В настоящее время я работаю над проектом Scala и столкнулся с трудностями при тестировании кода, который широко использует объекты Singleton.

У меня такие синглтоны:

object SomeSingleton {
  def someFunction(s: String): String = s + "b"
}

И где-то в проекте я использую его в методе, который хочу протестировать:

  val s = SomeSingleton.someFunction("a")

Я разрабатываю новые функции и хочу, чтобы SomeSingleton.someFunction возвращал какое-то конкретное значение в тестах без вызова реального метода. Я сделал это на Java с помощью Powermock, но мне не удалось найти способ сделать это в Scala. У меня есть идея, как я все еще могу это сделать, но это подразумевает изменение исходного кода на это:

object SomeSingleton extends SomeSingletonClass{}

class SomeSingletonClass {
  // Whole logic from SomeSingleton moves here
  def someFunction(s: String): String = s + "b"
}

Теперь я могу заменить использование SomeSingleton на SomeSingletonClass и правильно его смоделировать. Итак, вот мои опасения: проект немаленький, он не покрыт тестами на 100%, и я относительно новичок в Scala, поэтому я не уверен, могут ли это привести к каким-либо плохим последствиям? Это жизнеспособное решение? Я не хочу, чтобы мой устаревший код ломался в каком-то случайном месте из-за этого.

1
MaxNevermind 14 Июн 2017 в 22:06
Это хорошо...
 – 
OlivierBlanvillain
15 Июн 2017 в 01:30

1 ответ

Лучший ответ

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

  1. Да, введение класса SomeSingletonClass поможет с издевательством над классом, но обратной стороной этого является то, что он больше не синглтон. Я легко могу сделать val newSingleton = new SomeSingletonClass(), и вуаля, я создал новый объект. Лучший способ проверить синглтон - это просто протестировать синглтон напрямую. Я предполагаю, что ваш синглтон вызовет намного больше других синглтонов, и вы не хотите выполнять все эти побочные эффекты. Но чтобы правильно решить эту проблему, вам необходимо провести серьезный рефакторинг кода.

  2. PowerMock - очень мощный инструмент имитации в Java (возможно, слишком мощный). Способ, которым он может издеваться над вашими статическими методами / синглетонами, - это изменить байтовый код. Это работает в большинстве случаев, но когда это не так, вы совершенно не представляете, как это исправить. На моей предыдущей работе в Amazon мы часто использовали PowerMock, но затем постепенно стали избегать его из-за его магии черного ящика. Один из способов, который помог нам в этом, - это использование внедрения зависимостей, и вы можете легко внедрять фиктивные объекты в свои тесты.

  3. Я вижу, что вы имеете дело с устаревшим кодом, поэтому все переписать непросто (например, ввести внедрение зависимостей или даже новый SomeSingletonClass, который вы здесь пытаетесь). Я предлагаю вам не тратить слишком много времени на написание тестов для устаревшего кода. Вместо этого при написании нового кода постарайтесь сделать его тестируемым и реорганизуйте устаревший код по своему усмотрению.

1
Dat Nguyen 15 Июн 2017 в 07:09
« Я предлагаю вам, вероятно, не тратить слишком много времени на написание тестов для устаревшего кода. Вместо этого при написании нового кода постарайтесь сделать его тестируемым и реорганизуйте устаревший код по своему усмотрению. » Что ж, это именно то, что я планировал сделать, речь идет не о переписывании унаследованного кода, а о возможности протестировать новый.
 – 
MaxNevermind
15 Июн 2017 в 08:50
Рад, что смог помочь :)
 – 
Dat Nguyen
15 Июн 2017 в 09:38