Skip to content

Commit

Permalink
Tuple Assertions (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
alterationx10 committed Jul 7, 2023
1 parent 4722517 commit 8bdf836
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 2 deletions.
40 changes: 40 additions & 0 deletions test-opinions/src/main/scala/test/opinions/Mocks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,43 @@ extension [S, E: Tag, I, O: Tag](
* @return
*/
def expectF(e: E) = partialServiceMethod(e.expectedF)

extension [A, B](t: (Assertion[A], Assertion[B]))
/** Convert a Tuple of Assertions into an Assertion of a Tuple
*/
def asserted: Assertion[(A, B)] =
Assertion.hasField("_1", (tt: (A, B)) => tt._1, t._1) &&
Assertion.hasField("_2", (tt: (A, B)) => tt._2, t._2)

extension [A, B, C](t: (Assertion[A], Assertion[B], Assertion[C]))
/** Convert a Tuple of Assertions into an Assertion of a Tuple
*/
def asserted: Assertion[(A, B, C)] =
Assertion.hasField("_1", (tt: (A, B, C)) => tt._1, t._1) &&
Assertion.hasField("_2", (tt: (A, B, C)) => tt._2, t._2) &&
Assertion.hasField("_3", (tt: (A, B, C)) => tt._3, t._3)

extension [A, B, C, D](
t: (Assertion[A], Assertion[B], Assertion[C], Assertion[D])
)
/** Convert a Tuple of Assertions into an Assertion of a Tuple
*/
def asserted: Assertion[(A, B, C, D)] =
Assertion.hasField("_1", (tt: (A, B, C, D)) => tt._1, t._1) &&
Assertion.hasField("_2", (tt: (A, B, C, D)) => tt._2, t._2) &&
Assertion.hasField("_3", (tt: (A, B, C, D)) => tt._3, t._3) &&
Assertion.hasField("_4", (tt: (A, B, C, D)) => tt._4, t._4)

extension [A, B, C, D, E](
t: (Assertion[A], Assertion[B], Assertion[C], Assertion[D], Assertion[E])
)
/** Convert a Tuple of Assertions into an Assertion of a Tuple
*/
def asserted: Assertion[(A, B, C, D, E)] =
Assertion.hasField("_1", (tt: (A, B, C, D, E)) => tt._1, t._1) &&
Assertion.hasField("_2", (tt: (A, B, C, D, E)) => tt._2, t._2) &&
Assertion.hasField("_3", (tt: (A, B, C, D, E)) => tt._3, t._3) &&
Assertion.hasField("_4", (tt: (A, B, C, D, E)) => tt._4, t._4) &&
Assertion.hasField("_5", (tt: (A, B, C, D, E)) => tt._5, t._5)

// TODO more tuples :-(
67 changes: 65 additions & 2 deletions test-opinions/src/test/scala/test/opinions/MocksSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,22 @@ object MocksSpec extends ZIOSpecDefault:

trait SomeService:
def get(id: Int): Task[String]
def multi(a: String, b: Int): Task[String]

object SomeMockService extends Mock[SomeService]:
object Get extends Effect[Int, Throwable, String]
object Get extends Effect[Int, Throwable, String]
object Multi extends Effect[(String, Int), Throwable, String]

val compose: URLayer[Proxy, SomeService] =
ZLayer {
for {
proxy <- ZIO.service[Proxy]
} yield new SomeService:
override def get(id: RuntimeFlags): Task[String] = proxy(Get, id)
override def get(id: RuntimeFlags): Task[String] = proxy(Get, id)
override def multi(a: String, b: RuntimeFlags): Task[String] =
proxy(Multi, a, b)
}

override def spec: Spec[TestEnvironment with Scope, Any] =
suite("MocksSpec + ")(
test("expectWhen of values") {
Expand Down Expand Up @@ -114,5 +119,63 @@ object MocksSpec extends ZIOSpecDefault:
e1.getMessage == "boom",
e2.getMessage == "boom2"
)
},
test("tuple assertions") {
val Accessor = ZIO.serviceWithZIO[SomeService]
// We will use this as a recovery when our expectation fails,
// so our mock doesn't blow up the test.
val recovery = SomeMockService.Multi
.when(Assertion.anything)
.expectF(new Exception("boom"))
// We only care about the first arg
val justA = SomeMockService.Multi
.when(("a".eqTo, Assertion.anything).asserted)
.expect("success") || recovery
// We only care about the second arg
val just1 = SomeMockService.Multi
.when((Assertion.anything, 1.eqTo).asserted)
.expect("success") || recovery
// We care about both args
val a1 = SomeMockService.Multi
.when(("a".eqTo, 1.eqTo).asserted)
.expect("success") || recovery
// We don't care about anything,
// event just using Assertion.anything instead of this Tuple nonsense :-)
val anyAny = SomeMockService.Multi
.when((Assertion.anything, Assertion.anything).asserted)
.expect("success") || recovery

for {
_ <- Accessor(_.multi("a", 1))
.provide(justA)
_ <- Accessor(_.multi("a", 2))
.provide(justA)
_ <- Accessor(_.multi("b", 1)).flip
.provide(justA)
_ <- Accessor(_.multi("a", 1))
.provide(just1)
_ <- Accessor(_.multi("b", 1))
.provide(just1)
_ <- Accessor(_.multi("a", 2)).flip
.provide(just1)
_ <- Accessor(_.multi("a", 1))
.provide(a1)
_ <- Accessor(_.multi("a", 2)).flip
.provide(a1)
_ <- Accessor(_.multi("b", 1)).flip
.provide(a1)
_ <- Accessor(_.multi("b", 2)).flip
.provide(a1)
_ <- ZIO
.foreachDiscard(0 to 99) { _ =>
for {
strLen <- Random.nextIntBetween(1, 100)
str <- Random.nextString(strLen)
int <- Random.nextIntBetween(-1000, 1000)
_ <- Accessor(_.multi(str, int))
} yield ()
}
.provide(anyAny.exactly(100))
} yield assertCompletes
}
)

0 comments on commit 8bdf836

Please sign in to comment.