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

发布于 2024-10-31 19:00:44 字数 943 浏览 1 评论 0原文

我正在按照 Martin Fowler 的 演示模型 模式编写 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)
}

How can I mock the someLabel member of the MainView Trait using one open-source mocking Framework (< a href="http://easymock.org/" rel="nofollow">EasyMock, MockitoJMockit 等)进行单元测试?是否有另一个模拟框架(也许特定于 Scala)可以做到这一点?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

泼猴你往哪里跑 2024-11-07 19:00:44

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

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

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

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

纵山崖 2024-11-07 19:00:44

实际上,您不需要将某个东西作为 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)
}

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)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文