zio / zio-mock

https://zio.dev/zio-mock
Apache License 2.0
27 stars 33 forks source link

UnsatisfiedExpectationsException: null #35

Closed soujiro32167 closed 1 year ago

soujiro32167 commented 2 years ago

When running mocks with ZIO 2.0.2 and zio-mock 1.0.0-RC9, I get the following exception:

Exception in thread "zio-fiber-49" zio.mock.internal.MockException$UnsatisfiedExpectationsException: null
        at zio.mock.internal.MockState$.$anonfun$checkUnmetExpectations$3(MockState.scala:41)

To reproduce:

import zio._
import zio.mock.{Expectation, Mock}
import zio.stream.ZStream
import zio.test._
import zio.test.Assertion._

object reproduce extends ZIOSpecDefault {
  trait Foo {
    def createDocument(document: ZStream[Any, Throwable, Byte]): Task[Unit]
  }

  object FooMock extends Mock[Foo] {
    object CreateDocument extends Effect[ZStream[Any, Throwable, Byte], Throwable, Unit]

    val compose: URLayer[mock.Proxy, Foo] = ZLayer.fromFunction { (proxy: mock.Proxy) =>
      new Foo {
        override def createDocument(document: ZStream[Any, Throwable, Byte]): Task[Unit] =
          proxy(CreateDocument, document)
      }
    }
  }

  def spec = suite("mocks")(
    test("fail?") {
      for {
        _ <- ZIO.serviceWithZIO[Foo](_.createDocument(ZStream.empty))
      } yield assertCompletes
    }.provide(
      FooMock.CreateDocument(equalTo(ZStream.empty), Expectation.unit)
    )
  )
}

Scastie: https://scastie.scala-lang.org/soujiro32167/p6PBZRuGQwa7vXrmToKt8w/7

soujiro32167 commented 2 years ago

Looks like this happens when the input includes a ZStream

soujiro32167 commented 2 years ago

Actually, this is not even about streams. This error happens when ANY expectation is unmet 😱

lachezar commented 2 years ago

I just encountered this issue 😵‍💫

regiskuckaertz commented 2 years ago

Hey - I just rewrote a whole app to ZIO 2 and that was the hardest part. There is a way to get the reporting: use sut.exit to get details about the exception. It is far from ideal, but it works.

I have not looked into the code, but if given proper indications of where to look, I am happy to try and submit a fix for this.

vigoo commented 2 years ago

Hi @regiskuckaertz!

This is broken because of https://github.com/zio/zio-mock/issues/22 - it was a compromise as I did not have time to look into this but wanted to have a somewhat working version so other libraries like zio-aws can move forward in the migration process.

If you could help fixing it it would be really appreciated!

Some info:

regiskuckaertz commented 2 years ago

@vigoo ok thanks for that! I'm going to go through each error at a time and the first easy one is this expectation:

✖ Expected a call to zio.mock.MockConsole.Print(equalTo(foo)), but zio.mock.MockConsole.PrintLine was invoked instead.  (HINT: Remember order is important when considering mock invocations.)

is not met because the assertion is rendered like so:

private def renderAssertion(ass: Assertion[_]): String = bold(magenta(ass.toString()))

which uses the stock Java toString. The result is this:

✖ Expected a call to zio.mock.MockConsole.Print(Assertion(Meta(TestArrowF(zio.test.TestArrow$$$Lambda$39685/0x0000000803b93020@66a2c17f),None,None,Some(equalTo),None,None,None,None))), but zio.mock.MockConsole.PrintLine was invoked instead.  (HINT: Remember order is important when considering mock invocations.)

Is there an assertion renderer provided by zio-test?

regiskuckaertz commented 2 years ago

@swoogles Hi 👋 Sorry to pull you in, just wondering if you could point me to the right way of rendering an assertion here. I found ConsoleRenderer and something that looks useful maybe (renderRuntimeCause) but the output is a ExecutionResult and it is not clear how to plug the mock-specific error messages into it, or how to turn it into a string. Also the MockReporter only handles TestFailure.Runtime, should it also process TestFailure.Assertion?

swoogles commented 2 years ago

Hey @regiskuckaertz , I'm on holiday this week but will take a look on Sunday or Monday!

regiskuckaertz commented 2 years ago

@swoogles happy thanksgiving!

BalduinLandolt commented 1 year ago

What is the state on this? Could I potentially contribute?

dag2ww commented 1 year ago

+1 to above - it's really painful now if you have to deal with failing more complex tests... Any chance to have a fix for this pushed forward?

SirStoke commented 1 year ago

Hey! I managed to update zio-mock into failing with something like this:

- MockReporterSpec - Behavior - fail?
      Exception in thread "zio-fiber-471" zio.mock.internal.MockException$InvalidCallException: equalTo(zio.stream.ZStream@7bc5ab8a)
        at zio.mock.internal.ProxyFactory$$anon$1.$anonfun$invoke$37(ProxyFactory.scala:374)
        at zio.ZIO$.$anonfun$die$1(ZIO.scala:3095)
        at zio.ZIO$.$anonfun$failCause$1(ZIO.scala:3166)
        at zio.mock.MockReporterSpec.behaviorSuite(MockReporterSpec.scala:156)
        at zio.mock.MockReporterSpec.behaviorSuite(MockReporterSpec.scala:153)
        at zio.mock.MockReporterSpec.behaviorSuite(MockReporterSpec.scala:151)

Using the repro code in the original issue - would this be good enough to contribute? Or would you like to fix it into something better / more descriptive?

dag2ww commented 1 year ago

Hi, is there any chance to have a mocked method info as well - so in this case CreateDocument?

SirStoke commented 1 year ago

45 should fix this, as long as tests implement the MockReporter aspect (@@ MockReporter()) or the spec extends MockSpecDefault (which does the former automatically)

DGolubets commented 1 year ago

Hi, any progress on this?

mateuszbrzezinski commented 1 year ago

I have similar error, using example from docs:

image

and it fails with:

image

Is there any solution for that?

mateuszbrzezinski commented 1 year ago

So it seems real Random is called, not the MockRandom

mateuszbrzezinski commented 1 year ago

@adamgfraser are you aware about this issue? actually even tests in this project fail, any chance you can advise here?

regiskuckaertz commented 1 year ago

Just tested with the latest snapshot and that doesn't seem to happen anymore. Any chance we could get a new release @adamgfraser @vigoo ? 🙇‍♂️

adamgfraser commented 1 year ago

@regiskuckaertz Sure!

soujiro32167 commented 1 year ago

I've updated the scastie to latest ZIO and zio-mocks, but still getting the same behavior =[ https://scastie.scala-lang.org/soujiro32167/p6PBZRuGQwa7vXrmToKt8w/11

SirStoke commented 1 year ago

I've updated the scastie to latest ZIO and zio-mocks, but still getting the same behavior =[ https://scastie.scala-lang.org/soujiro32167/p6PBZRuGQwa7vXrmToKt8w/11

As mentioned above, you have to extend MockSpecDefault instead of ZIOSpecDefault. Your example works otherwise.

soujiro32167 commented 1 year ago

Totally missed that! Thanks @SirStoke