【Scala】ScalaTest ~ with Mockito ~

■ はじめに

https://dk521123.hatenablog.com/entry/2023/03/27/001306
https://dk521123.hatenablog.com/entry/2023/03/28/003906
https://dk521123.hatenablog.com/entry/2023/03/29/000014

の続き。

Scala の単体試験で、ScalaTest をベースにやってきたが、
今回は、ScalaTest + Mockito  (org.scalatestplus) で
モックを使ったテストしてみる。

目次

【0】ScalaTest の Mock
【1】Mockito
【2】初期設定
 補足:mockito-scala
【3】サンプル
 例1:mock() / when().thenReturn()
 例2:verify()
 補足:公式ドキュメントのサンプル

【0】ScalaTest の Mock

はじめ、ScalaTestでのMockは、Mockito の1択だろって
思っていたのだが、デフォルトで「import org.scalatest.mock.MockitoSugar」
がなくなっていたしで、改めてちゃんと調べてみたら、
公式ドキュメントに以下の記述あり。

https://www.scalatest.org/user_guide/testing_with_mock_objects

より抜粋
~~~~~~~~~~~~
ScalaMock
EasyMock
JMock
Mockito
~~~~~~~~~~~~

どれを選ぶかは、自分で使ってみて使い心地がいい方でいいと思うが
とりあえず、今回は、情報量が多い「Mockito」を使ってみる
(「EasyMock」と「Mockito」は、過去の自分が使っていたし)

ScalaMock

* PureのScala製のMock

http://scalamock.org/

EasyMock

* Java製のMock
 => 以下の関連記事を参照のこと

https://dk521123.hatenablog.com/entry/2010/01/28/234207

* 導入したい場合は、以下の公式ドキュメント参照

https://www.scalatest.org/plus/easymock

JMock

* こちらもJava製のMock

http://jmock.org/

* 導入したい場合は、以下の公式ドキュメント参照

https://www.scalatest.org/plus/jmock

【1】Mockito

* Java の モックツール
 => 詳細は、以下の関連記事を参照のこと

Mockito ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2014/07/18/233904
Mockito ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2014/07/19/121409

【2】初期設定

https://www.scalatest.org/plus/mockito

libraryDependencies ++= Seq(
  "org.scalatestplus" %% "mockito-4-6" % "3.2.15.0" % "test",
  "org.scalatest" %% "scalatest" % "3.2.15" % "test"
)

https://mvnrepository.com/artifact/org.scalatestplus
https://mvnrepository.com/artifact/org.scalatestplus/mockito-4-6

補足:mockito-scala

* 上記とは、別に「mockito-scala」ってのもある。
 => こっちの方がよさげ??

https://github.com/mockito/mockito-scala

libraryDependencies ++= Seq(
  "org.mockito" %% "mockito-scala" % "1.17.14" % "test"
)

https://takezoe.hatenablog.com/entry/2020/11/03/004143

【3】サンプル

例1:mock() / when().thenReturn()

import org.scalatest.funspec.AnyFunSpec
import org.scalatestplus.mockito.MockitoSugar
import org.mockito.Mockito.when

class Hello {
  def sayHello(name: String): String = {
    s"Hello, ${name}"
  }
}

// MockitoSugar trait provides some basic syntax sugar for Mockito.
class HelloTest extends AnyFunSpec with MockitoSugar {
  describe("For Hello World Test") {
    it ("Hello World For Mockito") {
      // First, create the mock object (mock オブジェクト作成用メソッド)
      val mockedHello = mock[Hello]

      // when().thenReturn(): 戻り値ありのメソッドに振る舞いを設定
      //  => 戻り値を「Fixed value」に変更
      when(mockedHello.sayHello("Mike")).thenReturn("Fixed value")
      assert("Fixed value" === mockedHello.sayHello("Mike"))
    }
  }
}

例2:verify()

import org.scalatest.funspec.AnyFunSpec
import org.scalatestplus.mockito.MockitoSugar
import org.mockito.Mockito.{verify, times, atLeastOnce, atLeast, atMost, never}

class Hello {
  def sayHello(name: String): String = {
    s"Hello, ${name}"
  }
}

// MockitoSugar trait provides some basic syntax sugar for Mockito.
class HelloTest extends AnyFunSpec with MockitoSugar {
  describe("For Hello World Test") {
    it ("Hello World For Mockito") {
      // First, create the mock object (mock オブジェクト作成用メソッド)
      val mockedHello = mock[Hello]
  
      mockedHello.sayHello("Mike")
      mockedHello.sayHello("Tom")
      mockedHello.sayHello("Tom")
      mockedHello.sayHello("Tom")

      // verify: メソッド呼び出しの妥当性検証
      verify(mockedHello, atLeastOnce()).sayHello("Mike")
      verify(mockedHello, atLeast(2)).sayHello("Tom")
      verify(mockedHello, atMost(2)).sayHello("Mike")
      verify(mockedHello, times(3)).sayHello("Tom")
      // verify(mockedHello, times(4)).sayHello("Tom") // !!Error!!
      verify(mockedHello, never()).sayHello("Sam")
    }
  }
}

補足:公式ドキュメントのサンプル

公式ドキュメントのサンプル

https://www.scalatest.org/plus/mockito

だが、さっぱり分からなかったが、
どうやら、Githubにあるテストコードの切れ端の模様。

https://github.com/scalatest/scalatestplus-mockito/blob/main/src/test/scala/org/scalatestplus/mockito/MockitoSugarSpec.scala

import もないのにわからんよ、、、

参考文献

https://takezoe.hatenablog.com/entry/2020/11/03/004143
https://inside.pixiv.blog/2022/11/24/120000
http://tkawachi.github.io/blog/2013/08/26/mockito-scala/
https://www.playframework.com/documentation/ja/2.4.x/ScalaTestingWithScalaTest

関連記事

ScalaTest ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2023/03/27/001306
ScalaTest ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2023/03/28/003906
ScalaTest ~ with ScalaCheck ~
https://dk521123.hatenablog.com/entry/2023/03/29/000014
ScalaTest ~ with Coverage ~
https://dk521123.hatenablog.com/entry/2023/08/07/222945
Scala ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2023/03/10/193805
Scala ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2023/03/12/184331
Scala ~ 基本編 / 繰り返し ~
https://dk521123.hatenablog.com/entry/2023/01/24/000000
Scala ~ 基本編 / Option型 ~
https://dk521123.hatenablog.com/entry/2023/03/09/000000
Scala ~ 基本編 / メソッド ~
https://dk521123.hatenablog.com/entry/2023/03/03/000000
Scala ~ 基本編 / クラス ~
https://dk521123.hatenablog.com/entry/2023/03/14/000857
Scala ~ 基本編 / コレクション ~
https://dk521123.hatenablog.com/entry/2023/03/13/000345
Scala ~ 基本編 / 日付・日時 ~
https://dk521123.hatenablog.com/entry/2023/03/08/000000
Scala ~ 基本編 / 正規表現
https://dk521123.hatenablog.com/entry/2023/03/18/034704
Scala ~ 基本編 / ジェネリック
https://dk521123.hatenablog.com/entry/2023/03/21/003817
ScalaEnum
https://dk521123.hatenablog.com/entry/2023/01/05/000000
Scala ~ ファイル名・パスの扱い ~
https://dk521123.hatenablog.com/entry/2023/03/11/000000
Scala ~ ファイルハンドリング ~
https://dk521123.hatenablog.com/entry/2023/01/03/000000
ScalaYAML
https://dk521123.hatenablog.com/entry/2023/03/16/012034
ScalaJDBC / DB接続 ~
https://dk521123.hatenablog.com/entry/2023/03/26/000950
ScalaAWS SDK
https://dk521123.hatenablog.com/entry/2023/03/24/211033
SBT ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2023/03/22/000000
SBT ~ 基本編 / build.sbt ~
https://dk521123.hatenablog.com/entry/2023/01/27/000000
SBT ~ 基本編 / sbtコマンド ~
https://dk521123.hatenablog.com/entry/2023/01/26/000000
SBT ~ sbtプラグイン
https://dk521123.hatenablog.com/entry/2023/01/25/000000
JavaでEmail ~ JavaMail / Text ~
https://dk521123.hatenablog.com/entry/2016/07/16/222422
JavaでEmail ~ JavaMail / 添付ファイル ~
https://dk521123.hatenablog.com/entry/2016/07/17/023459
JavaでEmail ~ SMTP認証 ~
https://dk521123.hatenablog.com/entry/2016/11/07/215251
JavaでEmail ~ SMTP認証 / DIGEST-MD5
https://dk521123.hatenablog.com/entry/2016/12/07/222229
JavaでEmail ~ JavaMail / TLS
https://dk521123.hatenablog.com/entry/2017/05/03/163219
JavaでEmail ~ JavaMail / Return-Path・Errors-To ~
https://dk521123.hatenablog.com/entry/2017/05/07/000344
Amazon SES ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2017/04/28/234103
Amazon S3 ~ Boto3編 ~
https://dk521123.hatenablog.com/entry/2019/10/21/230004
Amazon S3 ~ Boto3でファイル存在チェック ~
https://dk521123.hatenablog.com/entry/2022/02/26/182526
AWS Glue ~ Scalaでの実装 ~
https://dk521123.hatenablog.com/entry/2023/03/17/000000
AWS Glue ~ ローカル環境を作成する / Glue v3.0版 ~
https://dk521123.hatenablog.com/entry/2022/01/31/165650
LocalStack ~ ローカルで疑似AWSを作成する ~
https://dk521123.hatenablog.com/entry/2019/12/14/010524
LocalStack ~ ローカルで疑似Lambda/S3/DynamoDBを作成する ~
https://dk521123.hatenablog.com/entry/2019/12/16/231149
SparkからSnowflakeへの接続について考える
https://dk521123.hatenablog.com/entry/2023/03/19/013833
Mockito ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2014/07/18/233904
Mockito ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2014/07/19/121409
EasyMock ~入門編~
https://dk521123.hatenablog.com/entry/2010/01/28/234207
WSL ~ Windows Terminal ~
https://dk521123.hatenablog.com/entry/2020/12/10/094125