模拟包含抽象val成员的Scala特征

时间:2011-04-11 19:32:19

标签: scala mocking traits

我正在按照Martin Fowler的Presentation Model模式编写Swing应用程序。

我创建的traits包含已由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)
}

如何使用开源模拟框架(EasyMockMockitoJMockit等模拟someLabel特征的MainView成员。)进行单元测试?还有另一个模拟框架,也许特定于Scala可以做到这一点吗?

2 个答案:

答案 0 :(得分:3)

哈!在通勤之家看到它: - )。

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

请注意,我实际上没有对此进行测试,但它应该可以工作: - )。

答案 1 :(得分:3)

实际上,只要能够嘲笑它就不需要def。根据Scala的统一访问原则,defval从外部几乎相同。也就是说,对于val x,会生成名为x()的getter方法,并生成名为x_=(newX)的setter。

因此以下工作:

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