【问题标题】:Mocking Scala traits containing abstract val members模拟包含抽象 val 成员的 Scala 特征
【发布时间】:2011-04-11 19:32:18
【问题描述】:

我正在按照 Martin Fowler 的 Presentation Model 模式编写一个 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)
}

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

【问题讨论】:

    标签: scala mocking traits


    【解决方案1】:

    哈!在通勤回家的路上想通了:-)。

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

    请注意,我没有实际测试过这个,但它应该可以工作:-)。

    【讨论】:

      【解决方案2】:

      实际上,您不需要成为 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)
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多