我正在使用scala-test-containers、munit和munit-cats-effect以及Mill和 Scala 3 编写针对 postgres的skunk代码集成测试。我是Cats Effect的新手。
我正在努力实现的设置是:
- 测试套件启动 postgres 容器并为整个套件创建一次 skunk 会话(并在套件完成时停止容器)。
- 每个测试都在其自己的 skunk 数据库事务中进行回滚,以保持测试隔离。
下面是目前为止的代码,除了对 的调用rollback
(需要隐式 )之外,编译器都可以接受skunk.util.Origin
。我在 skunk 文档中没有看到对这种类型的任何引用,我不明白如何将其纳入范围。
我怎样才能让这段代码中的调用rollback
进行编译?缺少的隐式 Origin 在哪里?
import cats.effect.IO
import munit.CatsEffectSuite
import org.testcontainers.utility.DockerImageName
import cats.effect.kernel.Resource
import skunk.*
import skunk.implicits.*
import natchez.Trace.Implicits.noop
import munit.catseffect.IOFixture
import cats.implicits.catsSyntaxFlatMapOps
val container: Resource[IO, PostgreSQLContainer] =
Resource.make
(for {
c <- IO(PostgreSQLContainer(
DockerImageName.parse("postgres:17-alpine")
))
_ <- IO.blocking(c.start())
} yield c)
(c => IO.blocking(c.stop()))
val sessionResource: Resource[IO, Session[IO]] =
container.flatMap { c =>
Session.single[IO](
host = "localhost",
port = 5432,
user = c.username,
password = Some(c.password),
database = c.databaseName
)
}
def useWithRollback[T](s: Session[IO])(f: Transaction[IO] => IO[T]) =
s.transaction.use { xa =>
for {
result <- f(xa)
_ <- xa.rollback() // fails compilation: needs implicit skunk.util.Origin
} yield result
}
class PgIntegrationTests extends CatsEffectSuite:
val session = ResourceSuiteLocalFixture(
"skunk session",
sessionResource
)
override def munitFixtures = List(session)
def withDb[T](f: Transaction[IO] => IO[T]) =
useWithRollback(session())(f)
这个想法是,测试看起来像
test("something") {
withDb { xa =>
for {
result <- callMyCode(xa)
_ <- assertIO(result, <expected result>)
} yield ()
}
}
以上内容编译失败useWithRollback
,
[error] 41 | _ <- xa.rollback()
[error] | ^^^^^^^^^^^
[error] | None of the overloaded alternatives of method rollback in trait Transaction with types
[error] | (implicit o: skunk.util.Origin): cats.effect.IO[skunk.data.Completion]
[error] | (savepoint: xa.Savepoint)(implicit o: skunk.util.Origin): cats.effect.IO[skunk.data.Completion]
[error] | match arguments ()
据我所知,它正在寻找一个Origin
范围内的。我怎样才能将其纳入范围?为什么 skunk Transaction 页面(上面链接)在其示例中Origin
调用时没有这个问题?rollback
感谢您的时间。
PS:Mill 构建文件build.sc
:
import mill._, scalalib._
object devmap extends ScalaModule {
def scalaVersion = "3.5.1"
def ivyDeps = Agg(
ivy"org.tpolecat::skunk-core:0.6.4",
ivy"org.typelevel::cats-effect:3.5.7"
)
object test extends ScalaTests with TestModule.Munit {
def ivyDeps = Agg(
ivy"org.scalameta::munit::0.7.29",
ivy"org.typelevel::munit-cats-effect:2.0.0",
ivy"com.dimafeng::testcontainers-scala-postgresql:0.41.5",
ivy"org.postgresql:postgresql:42.7.4",
ivy"com.lihaoyi::pprint:0.9.0"
)
}
}
尝试一下这个: