Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

UnsatisfiedExpectationsException when mocks used as layers #63

Open
michalkoza opened this issue Sep 3, 2024 · 0 comments
Open

UnsatisfiedExpectationsException when mocks used as layers #63

michalkoza opened this issue Sep 3, 2024 · 0 comments

Comments

@michalkoza
Copy link

michalkoza commented Sep 3, 2024

I use Scala 3.3.3, ZIO 2.1.9, zio-mock: 1.0.0-RC12

Scastie: https://scastie.scala-lang.org/ICPrp4mkQJCBieDRi3gsiA

I have this trait:

trait MyTrait {
  def myMethod(myArg: String): ZIO[Any, Nothing, Int]
}

a mock for it:

import zio.*
import zio.mock.*

object MyTraitMock extends Mock[MyTrait] {
  object MyMethod extends Effect[String, Nothing, Int]

  val compose: URLayer[Proxy, MyTrait] =
    ZLayer {
      ZIO.serviceWith[Proxy] { proxy => (myArg: String) =>
        for {
          res <- proxy(MyMethod, myArg)
          _ <- ZIO.succeed(println(s"CALL, myArg: $myArg, res: $res"))
        } yield res
      }
    }
}

and a test suite with a buch of almost identical tests.
They should all pass, but only the first one and the last one pass. Others fail as if mock were never called, but it must have been.

import zio.mock.Expectation
import zio.test.Assertion.equalTo
import zio.test.{Spec, TestEnvironment, ZIOSpecDefault, assertTrue}
import zio.{Scope, ZIO}

object MyTraitSpec extends ZIOSpecDefault {
  override def spec: Spec[TestEnvironment & Scope, Any] =
    suite("suite")(
      test("test with atMost") {
        val layer = MyTraitMock.MyMethod(assertion = equalTo("arg1"), result = Expectation.value(10)).atMost(1).toLayer
        for {
          mockInstance <- ZIO.service[MyTrait].provideLayer(layer)
          result1 <- mockInstance.myMethod("arg1")
        } yield assertTrue(
          result1 == 10,
        )
      },

      test("test without quantifier") {
        val layer = MyTraitMock.MyMethod(assertion = equalTo("arg1"), result = Expectation.value(10)).toLayer
        for {
          mockInstance <- ZIO.service[MyTrait].provideLayer(layer)
          result1 <- mockInstance.myMethod("arg1")
        } yield assertTrue(
          result1 == 10,
        )
      },

      test("test with atLeast") {
        val layer = MyTraitMock.MyMethod(assertion = equalTo("arg1"), result = Expectation.value(10)).atLeast(1).toLayer
        for {
          mockInstance <- ZIO.service[MyTrait].provideLayer(layer)
          result1 <- mockInstance.myMethod("arg1")
        } yield assertTrue(
          result1 == 10,
        )
      },

      test("test with exactly") {
        val layer = MyTraitMock.MyMethod(assertion = equalTo("arg1"), result = Expectation.value(10)).exactly(2).toLayer
        for {
          mockInstance <- ZIO.service[MyTrait].provideLayer(layer)
          result1 <- mockInstance.myMethod("arg1")
          result2 <- mockInstance.myMethod("arg1")
        } yield assertTrue(
          result1 == 10,
          result2 == 10,
        )
      },

      test("test with exactly") {
        for {
          env <- MyTraitMock.MyMethod(assertion = equalTo("arg1"), result = Expectation.value(10)).exactly(2).toLayer.build
          mockInstance = env.get[MyTrait]
          result1 <- mockInstance.myMethod("arg1")
          result2 <- mockInstance.myMethod("arg1")
        } yield assertTrue(
          result1 == 10,
          result2 == 10,
        )
      }
    )
}

I think there is some issue with expectation count quantifiers when mocks are used as layers.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant