mockitoとscalatestについて

以下の投稿について、編集リクエストするレベルではないし、コメントするにも論点が多すぎてすごく長くなるため、別記事として自分のblogに書くことにしました

qiita.com

org.scalatest.mockitoのMockitoSugarがorg.scalatestplus.mockitoに移動されていて、既存のものはdeprecatedになっているよ、というエラー内容でした。

これはそのとおりなのですが、scalatest 3.0.8を使うなら、以下の対応が、ある意味間違いです

新たにscalatestplus-mockitoをDependencies.scalaに追加し、MockitoSugarを呼び出しているファイルのimport文の修正

scalatest 3.0.8を使うなら がややこしいのですが、つまりscalatest 3.1.xや3.2.xだと事情が異なるのですが、一旦それは後回しにします。

scalatestplusというpackage名のものを使え、という警告がややこしさの原因なのですが、scalatest 3.0.8時点においては、単にpackageやclass名がrenameされた、と、捉えるだけで良いです。*1

(ただし、それはscalatest 3.1.xにおいて、もっと大きな変更をするための準備なわけですが)

scalatest 3.0.8においてmockitoの依存はprovidedなので、別途mockitoの適切なversionの依存は足す必要がありますが(正確にはMockitoSugarすでに使ってるなら、すでにmockitoに依存してるはずなので、その場合基本何もしなくて良い)、基本的には警告に従って、renameするだけでよく、mockito-coreとscalatest以外の依存は必要ありません。 というか、(壊れる理由はここから説明しますが)scalatestplus-mockitoを加えると壊れます。

scalatestplus-mocktoはそれぞれ以下のように

基本的にscalatest 3.1.xに依存しています。 そしてscalatest 3.0.xと3.1.xはバイナリ互換がないため、当然scalatest 3.0.xと合わせるとエラーになります。

そして

mavenにscalatestplus-mockitoのリポジトリは存在しますが、まだ正式版はリリースされていないです。

というのは、scalatest 3.1.xの安定版が(この記事書いた時点では)リリースされていないため、おそらくそれを待ってscalatestplus-mockito含め、scalatestplusの各種ライブラリは安定版がリリースされるものと思われれます。(scalatestplus-playを除く)

そして、先程の

つまりscalatest 3.1.xや3.2.xだと事情が異なるのですが

の件ですが、つまりscalatest 3.0.xでは、mockitoやscalacheckなどの外部ライブラリのインテグレーションは同じリポジトリだったのですが、scalatest 3.1.xから(?)わけたい、という構想があるようです。

しかし、現時点ではscalatest 3.1.xは正式版ではないため、そのあたりの事情を完全に理解していたり、なにか3.1.x系を今すぐ使わないといけない人ではない限りは、scalatest 3.0.8を使っておいたほうが無難、だとは思います。

さて、別の話題に移りますが

Scalaでmockito使うならmockito-coreではなくこっちを使えとのこと。 mockito-scalaを使えばmockito-coreの適切なバージョンをプルしてくれるとのこと。

この2つの文に関して、それぞれ論点があり、(つまり合計2つ)、まず、後者の mockito-coreの適切なバージョンをプルしてくれる についてです。

http://repo1.maven.org/maven2/org/mockito/mockito-scala_2.12/1.5.9/mockito-scala_2.12-1.5.9.pom

結論から言うと 適切なバージョンをプルしてくれる すごくいい感じの仕組みがあるわけではなく、たまたまmockito-scalaがscalatest 3.0.8に依存していて、versionが合う、というだけのはずです。

つまり、scalatest 3.1.xがリリースされた後、mockito-scalaが古いままだと、同じように互換に問題が出る可能性は、将来普通に残っています。

さて、後者の Scalaでmockito使うならmockito-coreではなくこっちを使え についてですが、これは立場によって違うのでなんとも言えませんが、それぞれ自分が考えている範囲で、特徴などをまとめると

  • mockito-coreは、当然Scala関係なく使える、純Javaのライブラリで、Java界隈でも有名
  • mockito-coreは、(途中artifact id変わったりもしたが)結構古く、ある意味安定していると言える
  • デフォルト引数や、implicit、by nameと組み合わせた場合の挙動を知っておかないとハマることは多々あるが、とはいえmockito-coreをそのままscalaから使っても、それなりに使える
  • mockito-scalaはmockitoのラッパー
  • mocikto-scalaは、上記に挙げた、Scalaとmockitoを組み合わせた場合の面倒なところを、ある程度カバーするためのものである(あまり自信ない)
  • mockito-scalaは、よくもわるくも、結構若いライブラリ感がある
  • mockito-scalaScalaのマクロ使って実装されている部分があるので、うまく使いこなせばmockito単体では不可能な簡潔で便利な記述ができる可能性があるが、ハマるとマクロ特有の辛さに出会うかも・・・?、というトレードオフがある
  • mockito単体であまり困っていないなら、あえてmockito-scalaを、現時点では、そこまで積極的に使わなくていいと思う(個人的意見)
  • 新しい物好きな人はmockito-scala使えばいいと思うし、あまりそうでない人というか無難な方を選びたい人は、少なくとも今はmockito-scalaに手を出さなくてもいいかも・・・?

さて、ここまで色々書きましたが、さらに別の視点というか、ある意味一番言いたいこととしては、

scalatestのMockitoSugarは思ったより何もしてないので、(場合によっては雑にhelperメソッド作りつつ) MockitoSugarは使わずに、mockito-coreをそのまま使うのが、互換問題に一番悩まされない

ということです。以下を見てもらえばわかりますが、scalatest 3.0.8時点で、メソッドが4つあるだけであり、コメントが大半を占めており、それぞれのメソッドの実装はすべて1, 2行程度です。

https://github.com/scalatest/scalatest/blob/release-3.0.8/scalatest/src/main/scala/org/scalatestplus/mockito/MockitoSugar.scala

これだけのために互換問題に悩まされるのは、かなりわりに合わないと思うので、(必要ならMockitoSugarのメソッドをコピペしつつ) scalatest と mockito は完全に、それぞれそのまま使うと、scalatest 3.0.x から 3.1.x や 3.2.x に移行するときも、(scalatestplusやmockito-scalaの依存も考えずに)すんなり移行できるとおもいます。

*1:scalacheck関連など、その他のインテグレーションでも似たような変更がされています