代码之家  ›  专栏  ›  技术社区  ›  Jake

如何回滚臭鼬事务以进行集成测试?(缺少隐式原点)

  •  1
  • Jake  · 技术社区  · 5 月前

    我正在编写以下内容的集成测试 skunk 针对postgres的代码使用 scala-test-containers , munit munit-cats-effect ,使用 Mill 以及Scala 3。我是新手 Cats Effect .

    我正在努力实现的设置是:

    • 测试套件启动postgres容器,并为整个套件创建一次臭鼬会话(并在套件完成时停止容器)。
    • 每个测试都发生在自己的臭鼬数据库事务中,该事务会回滚,以保持测试的隔离。

    下面是到目前为止的代码,除了调用 rollback ,这需要一个隐式 skunk.util.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 在范围上。我该怎么带 产地 范围?为什么臭鼬交易页面(如上链接)在调用时没有出现此问题 回降 在其示例中?

    谢谢你的时间。

    P.S: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"
        )
      }
    }
    
    1 回复  |  直到 5 月前
        1
  •  1
  •   Luis Miguel Mejía Suárez    5 月前

    试试这个:

    def useWithRollback[T](s: Session[IO])(f: Transaction[IO] => IO[T]) =
      s.transaction.use { xa =>
        for {
          sp <- xa.savepoint
          result <- f(xa)
          _ <- xa.rollback(sp)
        } yield result
      }