Черты Mocking Scala, содержащие абстрактные члены val
Я пишу 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 ответа
Хах! Выяснили это на дороге домой:-).
Скала позволяет 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)
//...
}
}
Обратите внимание, что я на самом деле не проверял это, но это должно работать:-).
На самом деле, вам не нужно что-то, чтобы быть 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)
}