Reputation: 32284
I am writing a Swing application following Martin Fowler's Presentation Model pattern.
I create traits that contain abstract declarations of methods already implemented by Swing components:
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)
}
How can I mock the someLabel
member of the MainView
trait using one of open-source mocking frameworks (EasyMock, Mockito, JMockit, etc.) for unit testing? Is there another mocking framework, perhaps specific to Scala that can do this?
Upvotes: 4
Views: 2580
Reputation: 9364
Actually, you don't need something to be a def
just to be able to mock it. According to Scala's Uniform Access Principle, the def
and val
are virtually the same from the outside. That is, for a val x
a getter method named x()
is generated, and a setter named x_=(newX)
is generated.
Thus the following works:
@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)
}
Upvotes: 3
Reputation: 32284
Hah! Figured it out on the commute home :-).
Scala allows a val
in a concrete class to override a def
in a trait.
My traits become:
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)
// ...
}
My MainFrame
class does not need to change:
class MainFrame extends JFrame with MainView {
val someLabel = new JLabel with LabelMethods // ...But does not change
// in the class
// ...
}
My test case code looks like this:
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)
//...
}
}
Note that I have not actually tested this, but it should work :-).
Upvotes: 4