harness.zio.mock.Mock.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of harness-zio-mock_native0.4_3 Show documentation
Show all versions of harness-zio-mock_native0.4_3 Show documentation
Miscellaneous libraries/utilities for Scala.
The newest version!
package harness.zio.mock
import harness.zio.mock.error.MockError
import java.util.UUID
import zio.*
abstract class Mock[Z](implicit rTag: Tag[Z]) { myMock =>
private[mock] final val mockId: UUID = UUID.randomUUID
override final def hashCode: Int = mockId.hashCode
override final def equals(that: Any): Boolean =
that.asInstanceOf[Matchable] match {
case that: Mock[?] => this.mockId == that.mockId
case _ => false
}
final def name: String =
myMock.getClass.getSimpleName.stripSuffix("$")
abstract class Capability[I, R, E, A] { myCapability =>
private[mock] final val capabilityId: UUID = UUID.randomUUID
override final def hashCode: Int = capabilityId.hashCode
override final def equals(that: Any): Boolean =
that.asInstanceOf[Matchable] match {
case that: Capability[?, ?, ?, ?] => this.capabilityId == that.capabilityId
case _ => false
}
final def namePart: String =
myCapability.getClass.getSimpleName.stripSuffix("$")
final def name: String =
s"${myMock.name}<$namePart>"
// =====| |=====
private[mock] def getMock: Mock[Z] = myMock
// =====| |=====
/**
* Use these when creating the mocked layer.
* It allows you to specify how the capability should be implemented.
* These differ from seeded expectations,
* in that implementations don't care what order they are called in,
* or if they are called at all.
*/
object implement {
def zioI(f: I => ZIO[R, E, A]): Mocked[Z] =
Mocked.single(myCapability, f)
def zio(f: => ZIO[R, E, A]): Mocked[Z] =
zioI(_ => f)
def successI(f: I => A): Mocked[Z] =
zioI(i => ZIO.succeed(f(i)))
def success(f: => A): Mocked[Z] =
zioI(_ => ZIO.succeed(f))
def failureI(f: I => E): Mocked[Z] =
zioI(i => ZIO.fail(f(i)))
def failure(f: => E): Mocked[Z] =
zioI(_ => ZIO.fail(f))
}
/**
* Use these to seed expected calls to the capability.
* It is very important to note that ordering is enforced.
* If you seed:
* - `MyMock.Capability1.seed.success(1)`
* - `MyMock.Capability2.seed.success("test")`
* and then call `capability2()` before calling `capability1()`,
* ZIO will die with an error letting you know that a call to `capability2()` is expected next.
*/
object seed {
// append
def zioI(f: I => ZIO[R, E, A]): URIO[Proxy & Z, Unit] =
ZIO.serviceWithZIO[Proxy](_.appendSeed(myCapability, f))
def zio(f: => ZIO[R, E, A]): URIO[Proxy & Z, Unit] =
zioI(_ => f)
def successI(f: I => A): URIO[Proxy & Z, Unit] =
zioI(i => ZIO.succeed(f(i)))
def success(f: => A): URIO[Proxy & Z, Unit] =
zioI(_ => ZIO.succeed(f))
def failureI(f: I => E): URIO[Proxy & Z, Unit] =
zioI(i => ZIO.fail(f(i)))
def failure(f: => E): URIO[Proxy & Z, Unit] =
zioI(_ => ZIO.fail(f))
def expect(test: PartialFunction[I, Boolean])(implicit ev: Unit <:< A): URIO[Proxy & Z, Unit] =
zioI { i => ZIO.die(MockError.FailedExpectedSeed(myCapability, i)).unless(test.lift(i).getOrElse(false)).as(ev(())) }
object async {
def zioI(f: I => ZIO[R, E, A]): URIO[Proxy & Z, Unit] =
ZIO.serviceWithZIO[Proxy](_.appendAsyncSeed(myCapability, f))
def zio(f: => ZIO[R, E, A]): URIO[Proxy & Z, Unit] =
zioI(_ => f)
def successI(f: I => A): URIO[Proxy & Z, Unit] =
zioI(i => ZIO.succeed(f(i)))
def success(f: => A): URIO[Proxy & Z, Unit] =
zioI(_ => ZIO.succeed(f))
def failureI(f: I => E): URIO[Proxy & Z, Unit] =
zioI(i => ZIO.fail(f(i)))
def failure(f: => E): URIO[Proxy & Z, Unit] =
zioI(_ => ZIO.fail(f))
}
object prepend {
def zioI(f: I => ZIO[R, E, A]): URIO[Proxy & Z, Unit] =
ZIO.serviceWithZIO[Proxy](_.prependSeed(myCapability, f))
def zio(f: => ZIO[R, E, A]): URIO[Proxy & Z, Unit] =
zioI(_ => f)
def successI(f: I => A): URIO[Proxy & Z, Unit] =
zioI(i => ZIO.succeed(f(i)))
def success(f: => A): URIO[Proxy & Z, Unit] =
zioI(_ => ZIO.succeed(f))
def failureI(f: I => E): URIO[Proxy & Z, Unit] =
zioI(i => ZIO.fail(f(i)))
def failure(f: => E): URIO[Proxy & Z, Unit] =
zioI(_ => ZIO.fail(f))
}
object append {
def zioI(f: I => ZIO[R, E, A]): URIO[Proxy & Z, Unit] =
ZIO.serviceWithZIO[Proxy](_.appendSeed(myCapability, f))
def zio(f: => ZIO[R, E, A]): URIO[Proxy & Z, Unit] =
zioI(_ => f)
def successI(f: I => A): URIO[Proxy & Z, Unit] =
zioI(i => ZIO.succeed(f(i)))
def success(f: => A): URIO[Proxy & Z, Unit] =
zioI(_ => ZIO.succeed(f))
def failureI(f: I => E): URIO[Proxy & Z, Unit] =
zioI(i => ZIO.fail(f(i)))
def failure(f: => E): URIO[Proxy & Z, Unit] =
zioI(_ => ZIO.fail(f))
}
}
}
abstract class Effect[I, E, A] extends Capability[I, Any, E, A]
// =====| |=====
def empty: Mocked[Z] = Mocked.empty[Z](myMock)
protected def buildInternal(proxy: Proxy): Z
private[mock] final def build(proxy: Proxy): ZEnvironment[Z] = ZEnvironment(buildInternal(proxy))
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy