8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

名前渡し必要なメソッドのモックが地獄

Last updated at Posted at 2014-05-16

名前渡しするメソッドをもつやつのモックを定義しようとしたら地獄だった。

モック化する奴
trait Foo {
  def nyan(s: => String, repeat: Long)
}

このモックを verify しようとするとこんな風に書かないといけなくなる:

地獄.scala
import org.mockito.ArgumentMatcher
import org.scalatest.FunSuite
import org.scalatest.mock.MockitoSugar
import org.mockito.Mockito._
import org.mockito.Matchers._
import org.mockito.Matchers

class MockingWithByName extends FunSuite with MockitoSugar {

  test("mocking with a by-name param and AnyRef param") {
    val foo = mock[Foo]
    val sound = "nyaaaaan"
    val repeat = 1111L

    //

    foo.nyan(sound, repeat)

    //

    // ダメ
    //verify(foo, times(1)).nyan(sound, repeat)
    // => Argument(s) are different! Wanted:
    // 問答無用で Function0 にラップされて nyan に渡されるので、
    // 実際に呼ばれた時と、verify 時で、違う Function0 のインスタンスになってしまうため。

    // じゃあこうすると ...
    classOf[Foo].getMethod("nyan", classOf[Function0[_]], classOf[Long])
      .invoke(
        verify(foo),
        argThat(new ArgumentMatcher[Function0[_]] {
          override def matches(argument: Any): Boolean =
            argument.asInstanceOf[Function0[_]].apply() == sound
        }),
        //Matchers.eq(repeat) // ダメ
        // ↑ invoke の第二引数以降は AnyRef 期待されてるんだけど、
        // nyan 自体は scala.Long (AnyRef でないクラス)を期待してるので無理
        Matchers.eq(new java.lang.Long(repeat)) // こうする必要がある
      )

    // 完
  }
}

// モックにするやつ
trait Foo {
  def nyan(s: => String, repeat: Long)
}

スタブ作ったり、when で返り値の定義をする時にも同様の書き方が必要になります。

つらすぎる。今回使った Mockito 以外にも Java 向けのモックフレームワークを薄くラップしてる系のものは同じ悩みを抱えるはずなんですが、もっとスマートに書かける方法/モックフレームワークないの。

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?