Черты Mocking Scala, содержащие абстрактные члены val - PullRequest
4 голосов
/ 11 апреля 2011

Я пишу приложение Swing по шаблону Мартин Фаулер .

Я создаю черты, которые содержат абстрактные объявления методов, уже реализованных компонентами Swing:

trait LabelMethods {
  def setText(text: String)
  //...
}

trait MainView {
  val someLabel: LabelMethods
  def setVisible(visible: Boolean)
  // ...
}

class MainFrame extends JFrame with MainView {
  val someLabel = new JLabel with LabelMethods
  // ...
}

class MainPresenter(mainView: MainView) {
  //...
  mainView.someLabel.setText("Hello")
  mainView.setVisible(true)
}

Как я могу издеваться над членом someLabel черты MainView, используя одну из фреймворков с открытым кодом ( EasyMock , Mockito , JMockit и т. д.) для модульного тестирования? Есть ли еще одна насмешливая структура, возможно, специфическая для Scala, которая может это сделать?

Ответы [ 2 ]

3 голосов
/ 14 августа 2011

На самом деле, вам не нужно что-то, чтобы быть def, чтобы иметь возможность высмеивать это.Согласно принципу единого доступа Scala, def и val практически одинаковы снаружи.То есть для val x генерируется метод-получатель с именем x() и генерируется установщик с именем x_=(newX).

Таким образом, работает следующее:

@Test
def testUap() {
  abstract class A {
    val x: Int
  }
  val mock = Mockito mock classOf[A]
  Mockito when (mock.x) thenReturn 5
  Assert.assertEquals(5, mock.x)
}
3 голосов
/ 12 апреля 2011

Хах! Выяснили это на дороге домой: -).

Scala позволяет val в конкретном классе переопределить def в признаке.

Моими чертами становятся:

trait LabelMethods {
  def setText(text: String)
  //...
}

trait MainView {
  def someLabel: LabelMethods    // Note that this member becomes
                                 // a def in this trait...
  def setVisible(visible: Boolean)
  // ...
}

Мой MainFrame класс не нужно менять:

class MainFrame extends JFrame with MainView {
  val someLabel = new JLabel with LabelMethods // ...But does not change
                                               // in the class
  // ...
}

Код моего тестового примера выглядит так:

class TestMainPresenter {
  @Test def testPresenter {
    val mockLabel = EasyMock.createMock(classOf[LabelMethods])

    val mockView = EasyMock.createMock(classOf[MainView])
    EasyMock.expect(mockView.someLabel).andReturn(mockLabel)
    //... rest of expectations for mockLabel and mockView

    val presenter = new MainPresenter(mockView)
    //...
  }
}

Обратите внимание, что я на самом деле не проверял это, но оно должно работать: -).

...