7mind / izumi

Productivity-oriented collection of lightweight fancy stuff for Scala toolchain

Home Page:https://izumi.7mind.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[distage] Instance not available when running test

loathwine opened this issue · comments

I'm upgrading to distage 1.0.0 and managed to get my wiring test to succeed. However, when I try to run my distage tests I get the following error:

izumi.distage.model.exceptions.ProvisioningException: Provisioner failed on 0 of 9 required operations, just 1 succeeded:
- Unsatisfied preconditions:
  [!] Instance is not available in the object graph: {type.izumi.functional.bio.ApplicativeError3[=λ %1,%2,%3 → ZIO[-{Has[=package::System::Service] & Has[=package::Clock::Service] & Has[=package::Random::Service] & Has[=package::Blocking::Service] & Has[=package::Console::Service]},+2,+3]]}.
      Required by refs: ø

Here is a complete simplified test with the same error

import cats.Parallel
import cats.effect.{Async, ContextShift}
import distage.plugins.{PluginConfig, PluginDef}
import izumi.distage.model.definition.ModuleDef
import izumi.distage.model.effect.{QuasiAsync, QuasiIO, QuasiIORunner}
import izumi.distage.testkit.TestConfig
import izumi.distage.testkit.scalatest.Spec2
import izumi.functional.bio.Error2
import zio.interop.catz._
import zio.{Task, ZEnv, ZIO}

object MyZIOPlugin extends PluginDef {
  addImplicit[QuasiIO[ZIO[ZEnv, Throwable, +*]]]
  addImplicit[QuasiAsync[ZIO[ZEnv, Throwable, +*]]]
  make[QuasiIORunner[ZIO[ZEnv, Throwable, +*]]].from { iorunner: QuasiIORunner[Task] =>
    new QuasiIORunner[ZIO[ZEnv, Throwable, +*]] {
      override def run[A](f: => ZIO[ZEnv, Throwable, A]): A =
        iorunner.run(f.provideLayer(ZEnv.live))
    }
  }
  addImplicit[Error2[ZIO[ZEnv, +*, +*]]]
}

class MyTest extends Spec2[ZIO[ZEnv, +*, +*]] {
  trait MyComponent {
    def doSomething: Task[Unit]
  }
  object MyComponent {
    final class Impl(
      implicit cs: ContextShift[Task],
      async: Async[Task],
      parallel: Parallel[Task],
    ) extends MyComponent {
      override def doSomething: Task[Unit] = Task.unit
    }
  }

  override def config: TestConfig = TestConfig(
    pluginConfig = PluginConfig.const(MyZIOPlugin),
    moduleOverrides = new ModuleDef {
      make[MyComponent].from[MyComponent.Impl]
    },
    configBaseName = "my-test",
  )

  "My component" should {
    "do something" in { comp: MyComponent => comp.doSomething }
  }
}

I noticed that you completely removed ZIOPlugin in your example. However, I had a bit more in mine and haven't been able to remove it all yet.

I'm not a type-level expert but I thought that addImplicit[Error2[ZIO[ZEnv, +*, +*]]] would add the ApplicativeError3 instance from the error message.

Any help is appreciated!

commented

I'm not a type-level expert but I thought that addImplicit[Error2[ZIO[ZEnv, +, +]]] would add the ApplicativeError3 instance from the error message.

Try also adding addImplicit[ApplicativeError2[ZIO[ZEnv, +*, +*]]]. Error2 is a subtype of ApplicativeError2, but distage does not search for subtypes/supertypes, only for exact types. (unlike e.g. Guice)

commented

Also try using .addHas for your previous issue, I think in the long run it may be much easier to not use ZEnv as a global effect type, but use Task and .fromHas/.addHas to fulfill ZEnv and any other environment dependencies for components that require them.

commented

@Edvin-san
Seems like adding ApplicativeError2[ZIO[ZEnv, +*, +*]] fixed this particular issue, see fixed Scastie: https://scastie.scala-lang.org/6Ra4TQzdRSiMRUInsP6fdw

@neko-kai Awesome, thanks! I will try to eliminate ZEnv as a global effect type.