Mocking Scala traits containing abstract val members

自作多情 提交于 2019-12-10 17:09:22

问题


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?


回答1:


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




回答2:


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


来源:https://stackoverflow.com/questions/5626491/mocking-scala-traits-containing-abstract-val-members

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!