Code Monkey home page Code Monkey logo

munit-cats-effect's Introduction

munit-cats-effect Continuous Integration Maven Central

Integration library for MUnit and cats-effect.

Binaries

For versions 2.0.0-M1 and above:

libraryDependencies += "org.typelevel" %%% "munit-cats-effect" % version % "test"

Please note that only Cats Effect 3 is supported for versions 2.0.0-M1 and above.

For versions 1.0.7 and below:

Cats Effect 2 integration is provided via:

libraryDependencies += "org.typelevel" %%% "munit-cats-effect-2" % version % "test"

Cats Effect 3 integration is provided via:

libraryDependencies += "org.typelevel" %%% "munit-cats-effect-3" % version % "test"

Builds are available for Scala 2.12, 2.13, and 3 for both the JVM and Scala.js.

Getting Started

The munit.CatsEffectSuite trait provides the ability to write tests that return IO and SyncIO values without needing to call any unsafe methods (e.g. unsafeRunSync()).

import cats.effect.{IO, SyncIO}
import munit.CatsEffectSuite

class ExampleSuite extends CatsEffectSuite {

  test("tests can return IO[Unit] with assertions expressed via a map") {
    IO(42).map(it => assertEquals(it, 42))
  }

  test("alternatively, assertions can be written via assertIO") {
    assertIO(IO(42), 42)
  }

  test("or via assertEquals syntax") {
    IO(42).assertEquals(42)
  }

  test("or via plain assert syntax on IO[Boolean]") {
    IO(true).assert
  }

  test("SyncIO works too") {
    SyncIO(42).assertEquals(42)
  }

  import cats.effect.std.Dispatcher

  val dispatcher = ResourceFixture(Dispatcher.parallel[IO])

  dispatcher.test("resources can be lifted to munit fixtures") { dsp =>
    dsp.unsafeRunAndForget(IO(42))
  }
}

There are more assertion functions like interceptIO and interceptMessageIO as well as syntax versions intercept and interceptMessage. See the CatsEffectAssertions trait for full details.

Every assertion in CatsEffectAssertions for IO-value or SyncIO-value is an IO computation under the hood. If you are planning to use multiple assertions per one test suite, therefore, they should be composed. Otherwise will calculate only the last assertion.

import cats.syntax.all._
import cats.effect.{IO, SyncIO}
import munit.CatsEffectSuite

class MultipleAssertionsExampleSuite extends CatsEffectSuite {
  test("multiple IO-assertions should be composed") {
    assertIO(IO(42), 42) *>
      assertIO_(IO.unit)
  }

  test("multiple IO-assertions should be composed via for-comprehension") {
    for {
      _ <- assertIO(IO(42), 42)
      _ <- assertIO_(IO.unit)
    } yield ()       
  }

  test("multiple SyncIO-assertions should be composed") {
    assertSyncIO(SyncIO(42), 42) *>
      assertSyncIO_(SyncIO.unit)
  }
    
  test("multiple SyncIO-assertions should be composed via for-comprehension") {
    for {
      _ <- assertSyncIO(SyncIO(42), 42)
      _ <- assertSyncIO_(SyncIO.unit)
    } yield ()       
  }
}

Suite-local fixtures

MUnit supports reusable suite-local fixtures that are instantiated only once for the entire test suite. This is useful when an expensive resource (like an HTTP client) is needed for each test case but it is undesirable to allocate a new one each time.

import cats.effect.{IO, Resource}
import fs2.io.file.Files

class SuiteLocalExampleSuite extends CatsEffectSuite {

  val myFixture = ResourceSuiteLocalFixture(
    "my-fixture",
    Resource.make(IO.unit)(_ => IO.unit)
  )
  
  val tempFileFixture = ResourceSuitLocalFixture(
    "temp-file",
    Files[IO].tempFile
  )

  override def munitFixtures = List(myFixture, tempFileFixture)

  test("first test") {
    IO(myFixture()).assertEquals(())
  }

  test("second test") {
    IO(myFixture()).assertEquals(())
  }
  
  test("third test") {
    IO(tempFileFixture()).flatMap { file =>
      Files[IO].exists(file).assert
    }
  }

}

Notice that this integration is not pure; myFixture is mutated internally when the framework initializes the fixture, so the same reference that is used from test cases must be specified in munitFixtures. Otherwise an exception FixtureNotInstantiatedException will be thrown.

munit-cats-effect's People

Contributors

ahjohannessen avatar alejandrohdezma avatar armanbilge avatar cquiroz avatar danicheg avatar diesalbla avatar djspiewak avatar kevinboyette avatar larsrh avatar milanvdm avatar mpilquist avatar mtomko avatar rossabaker avatar scala-steward avatar systemfw avatar timwspence avatar typelevel-steward[bot] avatar valencik avatar vasilmkd avatar z1kkurat avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

munit-cats-effect's Issues

Release version doesn't match with artifact version

Hey ๐Ÿ™‚๐Ÿ‘‹!

I was trying to play a bit with the library and I had the following issue

Context

Scala Version: 2.13
Sbt Version: 1.4.1
Munit Version: 0.7.14

Expectation

If I use the last github tag release to set the the library dependency, it will be downloaded correctly.

Actual Behaviour

I checked the release tags, and I used the last one to use the library:

 libraryDependencies += "org.typelevel" %% "munit-cats-effect-2" % "0.3.0" % "test"

But an error appears:

2020.10.25 20:35:04 INFO  [error] sbt.librarymanagement.ResolveException: Error downloading org.typelevel:munit-cats-effect-2_2.13:0.3.0
2020.10.25 20:35:04 INFO  [error]   Not found
2020.10.25 20:35:04 INFO  [error]   Not found
2020.10.25 20:35:04 INFO  [error]   not found: /Users/marc/.ivy2/local/org.typelevel/munit-cats-effect-2_2.13/0.3.0/ivys/ivy.xml
2020.10.25 20:35:04 INFO  [error]   not found: https://repo1.maven.org/maven2/org/typelevel/munit-cats-effect-2_2.13/0.3.0/munit-cats-effect-2_2.13-0.3.0.pom

I checked the artifact repository and I found theses versions

image

I used the version "0.4-5f8036d", and it works

Add a fixture which provides a cats.effect.std.Dispatcher

Not sure if we need this or not. We can currently do this:

val dispatcher = CatsEffectFixture.fromResource(Dispatcher[IO])

dispatcher.test("foo") { dispatcher => ... }

We could instead instantiate a dispatcher in every CatsEffectSuite and setup/tear down in beforeAll/afterAll. Thoughts?

Promise exception on 2.12

In one of my tests I'm using a fixture and I see these messages on the log, surprisingly in 2.12 only and the error itself runs fine it just print these

java.lang.IllegalStateException: Promise already completed.
  | => oat scala.concurrent.Promise.complete(Promise.scala:53)
        at scala.concurrent.Promise.complete$(Promise.scala:52)
        at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:187)
        at scala.concurrent.Promise.failure(Promise.scala:104)
        at scala.concurrent.Promise.failure$(Promise.scala:104)
        at scala.concurrent.impl.Promise$DefaultPromise.failure(Promise.scala:187)
        at scala.concurrent.impl.Promise.$anonfun$transformWith$1(Promise.scala:45)
        at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)
        at munit.Suite$$anon$1.execute(Suite.scala:26)

The error itself is kind of complicated but I could try to produce a minimal reproduction in needed

Tests hang when testing with scala-cli

Tests never finish when being ran with scala-cli. Same tests finish when runnning with sbt. If i make a test fail it does not hang.

Minimal case that hangs, also happens for FunSuite. If I remove the dep on munit-ce it works again.

project.scala

//> using scala "3.3.1"

//> using test.dep "org.scalameta::munit:0.7.29"
//> using dep "org.typelevel::cats-effect:3.5.2"
//> using test.dep "org.typelevel::munit-cats-effect:2.0.0-M3"

Tests

import munit.CatsEffectSuite
import cats.effect.IO

class MyTestSuite extends CatsEffectSuite:

  test("minimal"):
    IO:
      assert(true)

Scala CLI version: 1.0.4

ResourceSuiteLocalFixture is allocated after suite's beforeAll()

The following code

import cats.effect.IO
import cats.effect.kernel.Resource
import munit.CatsEffectSuite


class TestWsResource extends CatsEffectSuite {

  val d = ResourceSuiteLocalFixture(
    "Double resource",
    Resource.make(IO.println("Allocating resource") >> IO(4.0))(d => IO.println(s"Releasing resource: $d"))
  )

  override val munitFixtures = List(d)

  test("resource") {
    IO.println(s"Using resource: ${d()}")
  }

  override def beforeAll(): Unit = {
    // println(s"{${d()}")
    println(s"{d()}")
  }

  override def afterAll(): Unit = {
    println(s"After all ${d()}")
  }

}

produces

{{d()}
Allocating resource
Using resource: 4.0
After all 4.0
Releasing resource: 4.0

Changing beforeAll() to

  override def beforeAll(): Unit = {
    println(s"{${d()}")
  }

results in

Allocating resource
Releasing resource: 4.0

Process finished with exit code 255

munit.catseffect.ResourceFixture$FixtureNotInstantiatedException: The fixture `Double resource` was not instantiated. Override `munitFixtures` and include a reference to this fixture.

It looks that suite local resource is allocated after beforeAll and released after afterAll . Is this the desired behavior?

scalafmt is not enforced in CI

java.io.IOException: Supplied file /home/runner/work/munit-cats-effect/munit-cats-effect/target/sonatype-staging/0.4-dca45a0-SNAPSHOT is a not an existing directory!

Experiment with time mocking APIs

How should tests be structured to best take advantage of this and reflect the capability to users in an idiomatic fashion? Not sure! typelevel/cats-effect#2276 exposes a new TestControl runtime which makes it relatively straightforward to test IO programs under artificial time control.

`NoSuchMethodError` When Using `org.scalameta::munit:1.0.0-M7`

๐Ÿ‘‹๐Ÿฝ Hello,

I encountered an issue running CatsEffectSuite tests with cats-effect3 and the latest milestone of munit see below for minimum reproduction:

repro.scala

//> using scala "2.13"
//> using lib "org.typelevel::cats-effect:3.4.5"
//> using lib "org.scalameta::munit:1.0.0-M7"
//> using lib "org.typelevel::munit-cats-effect-3:1.0.7"

import cats.effect.IO
import munit.CatsEffectSuite

class Repro extends CatsEffectSuite {
  test("repro") {
    IO(3).assertEquals(3)
  }
}

> scala-cli test .

Error:

==> X Repro.initializationError  0.001s java.lang.NoSuchMethodError: 'void munit.ValueTransforms$ValueTransform.<init>(munit.FunSuite, java.lang.String, scala.PartialFunction)'
    at munit.CatsEffectSuite.<init>(CatsEffectSuite.scala:42)
    at Repro.<init>(files.scala:9)
    at jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:67)
    at java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:128)
    at jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:341)
    at java.lang.Class.newInstance(Class.java:677)
    at munit.MUnitRunner$$anonfun$$lessinit$greater$1.apply(MUnitRunner.scala:33)
    at munit.MUnitRunner$$anonfun$$lessinit$greater$1.apply(MUnitRunner.scala:33)
    at munit.MUnitRunner.<init>(MUnitRunner.scala:35)
    at munit.MUnitRunner.<init>(MUnitRunner.scala:33)
    at jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:67)
    at java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:483)
    at munit.internal.junitinterface.JUnitComputer.getRunner(JUnitComputer.java:75)
    at munit.internal.junitinterface.JUnitComputer$1.runnerForClass(JUnitComputer.java:65)
    ...

With org.scalameta::munit:0.7.29:

Repro:
  + repro 0.041s

Lack of Cross-Platform Support for ResourceSuiteLocalFixture

For the same reason this is useful on the jvm, it would be useful when running for js.

Currently options are to have a build specific test and spin up resources on each test on js, or spin up resources on each test on both jvm and js, while ideally it would be nice to use this feature in cross-compatible code.

Integrate with upcoming munit v1

Opening the issue to kick things off, munit v1 is still in the milestone stage.
https://github.com/scalameta/munit/releases/tag/v1.0.0-M1

The most notable changes (so far) are that it now supports async suite-local Fixtures ๐ŸŽ‰ . Much gratitude to @danicheg for PRing this ๐Ÿ‘

My biggest question is: for how long do we still intend to support both CE2 and CE3? Since we are bumping version numbers anyway, I'd be happy to use this opportunity to dump CE2 and the acrobatics this repo uses to share code between them.

Add 'strict' Suite

MUnit allows overriding a TestValue to a value to enforce a test always returns that type. In the example it is used for Future.

Due to the lazy evaluation of IO I think it'd be very useful if I could enforce my test would always return an IO to prevent code from never being run. ScalaTest has recently changed their suites to be AnySpec (can return Any) or AsyncSpec (must return a Future). munit-cats-effect could introduce something similar for returned IO's by overriding MUnit's TestValue.

If added to munits-cats-effect, users should probably still have a choice (just like in ScalaTest) between the two styles. And maybe 'strict' should not be the default? I don't have a strong opinion on what the naming should be.

For implementation some refactoring would probably be needed. TestType is made final in munit.FunSuite so the new suite would have to extend from munit.Suite. Code sharing between the two styles is probably also wanted. I'd be interested in helping out with a PR if this is wanted

Non release builds published to Maven

This may not be a bug but it seems a little unusual to me. It seems all non PR builds are been published to Maven. I noticed this because I have a giter8 project which attempts to use the latest stable version of munit-cats-effect-2 and the search used by giter8 only returns non release builds. This is different behaviour to how munit publishes builds as can be seen from the search result.

Override MUnit's `ExecutionContext` on ScalaJS and CE3

So the problem here is that MUnit is probably using ExecutionContext.global on ScalaJS, which in turn means that it is relying on the microtask queue. This means a couple of things, including the fact that setTimeout isn't working correctly, but it also means that any test suite which relies on parallel execution of tests as observed from within Cats Effect is definitely not going to see actual parallelism.

The solution here is to pull the ExecutionContext out of IORuntime.global and force MUnit to use it rather than its default executor, at least on ScalaJS. I'm not sure MUnit makes this possible (Specs2 doesn't); if it doesn't, then we should open a feature request upstream.

Snapshot publishing is failing

Two last attempts were failed #1, #2. I don't confident is this a flaky thing, so let's take notice.

[error] java.net.ProtocolException: Server redirected too many  times (20)
[error] 	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[error] 	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
[error] 	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
[error] 	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
[error] 	at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1952)
[error] 	at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1[94](https://github.com/typelevel/munit-cats-effect/runs/5434252350?check_suite_focus=true#step:20:94)7)
[error] 	at java.security.AccessController.doPrivileged(Native Method)
[error] 	at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1946)
[error] 	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1516)
[error] 	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1500)
[error] 	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:268)
[error] 	at org.apache.ivy.util.url.BasicURLHandler.upload(BasicURLHandler.java:288)
[error] 	at org.apache.ivy.util.url.URLHandlerDispatcher.upload(URLHandlerDispatcher.java:82)
[error] 	at org.apache.ivy.util.FileUtil.copy(FileUtil.java:150)
[error] 	at org.apache.ivy.plugins.repository.url.URLRepository.put(URLRepository.java:84)
[error] 	at sbt.internal.librarymanagement.ConvertResolver$LocalIfFileRepo.put(ConvertResolver.scala:368)
[error] 	at org.apache.ivy.plugins.repository.AbstractRepository.put(AbstractRepository.java:130)
[error] 	at sbt.internal.librarymanagement.ConvertResolver$ChecksumFriendlyURLResolver.put(ConvertResolver.scala:118)
[error] 	at sbt.internal.librarymanagement.ConvertResolver$ChecksumFriendlyURLResolver.put$(ConvertResolver.scala:[105](https://github.com/typelevel/munit-cats-effect/runs/5434252350?check_suite_focus=true#step:20:105))
[error] 	at sbt.internal.librarymanagement.ConvertResolver$$anonfun$defaultConvert$lzycompute$1$PluginCapableResolver$1.put(ConvertResolver.scala:165)
[error] 	at org.apache.ivy.plugins.resolver.RepositoryResolver.publish(RepositoryResolver.java:216)
[error] 	at sbt.internal.librarymanagement.IvyActions$.$anonfun$publish$5(IvyActions.scala:504)
[error] 	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
[error] 	at scala.util.Try$.apply(Try.scala:213)
[error] 	at sbt.internal.librarymanagement.IvyUtil$.retryWithBackoff(IvyUtil.scala:22)
[error] 	at sbt.internal.librarymanagement.IvyActions$.$anonfun$publish$4(IvyActions.scala:503)
[error] 	at sbt.internal.librarymanagement.IvyActions$.$anonfun$publish$4$adapted(IvyActions.scala:501)
[error] 	at scala.collection.Iterator.foreach(Iterator.scala:943)
[error] 	at scala.collection.Iterator.foreach$(Iterator.scala:943)
[error] 	at scala.collection.AbstractIterator.foreach(Iterator.scala:1431)
[error] 	at scala.collection.IterableLike.foreach(IterableLike.scala:74)
[error] 	at scala.collection.IterableLike.foreach$(IterableLike.scala:73)
[error] 	at scala.collection.AbstractIterable.foreach(Iterable.scala:56)
[error] 	at sbt.internal.librarymanagement.IvyActions$.publish(IvyActions.scala:501)
[error] 	at sbt.internal.librarymanagement.IvyActions$.$anonfun$publish$3(IvyActions.scala:143)
[error] 	at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23)
[error] 	at sbt.internal.librarymanagement.IvyActions$.withChecksums(IvyActions.scala:157)
[error] 	at sbt.internal.librarymanagement.IvyActions$.withChecksums(IvyActions.scala:150)
[error] 	at sbt.internal.librarymanagement.IvyActions$.$anonfun$publish$1(IvyActions.scala:143)
[error] 	at sbt.internal.librarymanagement.IvyActions$.$anonfun$publish$1$adapted(IvyActions.scala:133)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.$anonfun$withModule$1(Ivy.scala:251)
[error] 	at sbt.internal.librarymanagement.IvySbt.$anonfun$withIvy$1(Ivy.scala:215)
[error] 	at sbt.internal.librarymanagement.IvySbt.sbt$internal$librarymanagement$IvySbt$$action$1(Ivy.scala:77)
[error] 	at sbt.internal.librarymanagement.IvySbt$$anon$1.call(Ivy.scala:87)
[error] 	at xsbt.boot.Locks$GlobalLock.withChannel$1(Locks.scala:[113](https://github.com/typelevel/munit-cats-effect/runs/5434252350?check_suite_focus=true#step:20:113))
[error] 	at xsbt.boot.Locks$GlobalLock.withChannelRetries$1(Locks.scala:91)
[error] 	at xsbt.boot.Locks$GlobalLock.$anonfun$withFileLock$1(Locks.scala:119)
[error] 	at xsbt.boot.Using$.withResource(Using.scala:12)
[error] 	at xsbt.boot.Using$.apply(Using.scala:9)
[error] 	at xsbt.boot.Locks$GlobalLock.withFileLock(Locks.scala:119)
[error] 	at xsbt.boot.Locks$GlobalLock.ignoringDeadlockAvoided(Locks.scala:71)
[error] 	at xsbt.boot.Locks$GlobalLock.withLock(Locks.scala:59)
[error] 	at xsbt.boot.Locks$.apply0(Locks.scala:47)
[error] 	at xsbt.boot.Locks$.apply(Locks.scala:36)
[error] 	at sbt.internal.librarymanagement.IvySbt.withDefaultLogger(Ivy.scala:87)
[error] 	at sbt.internal.librarymanagement.IvySbt.withIvy(Ivy.scala:209)
[error] 	at sbt.internal.librarymanagement.IvySbt.withIvy(Ivy.scala:206)
[error] 	at sbt.internal.librarymanagement.IvySbt$Module.withModule(Ivy.scala:250)
[error] 	at sbt.internal.librarymanagement.IvyActions$.publish(IvyActions.scala:133)
[error] 	at sbt.Classpaths$.$anonfun$publishTask$4(Defaults.scala:3556)
[error] 	at sbt.Classpaths$.$anonfun$publishTask$4$adapted(Defaults.scala:3549)
[error] 	at scala.Function1.$anonfun$compose$1(Function1.scala:49)
[error] 	at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:62)
[error] 	at sbt.std.Transform$$anon$4.work(Transform.scala:68)
[error] 	at sbt.Execute.$anonfun$submit$2(Execute.scala:282)
[error] 	at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:23)
[error] 	at sbt.Execute.work(Execute.scala:291)
[error] 	at sbt.Execute.$anonfun$submit$1(Execute.scala:282)
[error] 	at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265)
[error] 	at sbt.CompletionService$$anon$2.call(CompletionService.scala:64)
[error] 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] 	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error] 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:[114](https://github.com/typelevel/munit-cats-effect/runs/5434252350?check_suite_focus=true#step:20:114)9)
[error] 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error] 	at java.lang.Thread.run(Thread.java:750)

assert for IO[Boolean]

In munit there is plain assert besides assertEquals. The equivalent for munit-cats-effect is:
IO(true).assertEquals(true)

Would it make sense to have the option of
IO(true).assert

If so I could send a PR

CatsEffectSuite runs inner IO if it receives IO[IO[A]]

A colleague of mine spent hours fighting with Resource in a test due to a trivial mistake (map vs flatMap).
I've found out that CatsEffectSuite does something really odd in this case however: it seems to run unsafeToFuture on both the outer and inner IO when it receives IO[IO[A]], maybe there is some implicit conversion happening.
The repro should make it clear:

import cats.effect._
import munit.CatsEffectSuite
import scala.concurrent.duration._

class Repro extends CatsEffectSuite {
  test("use after close") {
    Resource.make(IO.println("Open"))(_ => IO.println("Close")).use { _ =>
      IO.println("Enjoy: ").map { _ =>
        IO.sleep(1.second) >> IO.println("Use after close!")
      }
    }
  }

  test("minimised") {
    IO.println("Nope")
    IO.println("Hello").map { _ => IO.println("Surely not") }
  }
}

/*
sbt:root> testOnly *Repro*
[info] Passed: Total 0, Failed 0, Errors 0, Passed 0
[info] No tests to run for Test / testOnly
Open
Enjoy: 
Close
Use after close!
Repro:
  + use after close 1.105s
Hello
Surely not
  + minimised 0.002s
[info] Passed: Total 2, Failed 0, Errors 0, Passed 2
[success] Total time: 1 s, completed 30 Nov 2021, 14:48:32
*/

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.