开发者

Mocking Scala traits containing abstract val members

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 开发者_StackOverflow中文版= 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?


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 :-).


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)
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜