ChatGPT says this should work, but looks like it is mistaken :/
      trait Foo { def s: String }
      case object A extends Foo { def s = "A" }
      case object B extends Foo { def s = "B" }
      test("Replace a service in ZIO") {
        val layer = ZLayer.succeed[Foo](A)
        val otherLayer = ZLayer.succeed[Foo](B)
        val app = (for {
          foo <- ZIO.service[Foo]
          bar <- ZIO.service[String]
        } yield foo.s + bar).provide(layer, ZLayer.succeed("foo"))
        val otherApp = app.provideSomeLayer(otherLayer)
        otherApp.map { s => assertTrue(s == "Bfoo") }
      }
I have an app here that has service A and string "foo". Trying to create the otherApp from it, replacing A with B, and keeping the rest ("foo") as is.
But no luck - this test fails because the resulting value is still "Afoo" rather than "Bfoo".
What am I doing wrong?
Also (on a sort of different topic), if I change provide there to
provideLayer(layer).provide(ZLayer.succeed("foo"), it no longer compiles saying it wants layer to be Foo with String. Is there no way to provide some dependencies to the effect, and leave others undefined?
And one more noob question, while I have your attention. At which point do these ZIOs actually run? Does this test run them both? Or will it only run the otherApp because it is the only one that is used to produce the return value?
 
                        
I don't think you can "replace" a layer once it's been provided.
I'm actually even surprised that your usage of
provideSomeLayerdoesn't raise an error because you provided too much layers. Usually it fails to compile when a unnecessary layer is provided.Yes,
provideSomewill do it:If you were outside a ZIO test, nothing would run until you give the
ZIOto a "runtime" with something like this:But in a ZIO test context, the framework runs the effects for you. So you don't need this "runtime" thing. And I assume that it only runs the effect of the returned value.