Closed nomisRev closed 1 year ago
We could also consider adding a suspendable install that's only usable from within a test or callback.
On Wed, Jun 29, 2022, 3:15 AM Simon Vergauwen @.***> wrote:
@.**** commented on this pull request.
In kotest-assertions-arrow-fx-coroutines/src/commonMain/kotlin/io/kotest/assertions/arrow/fx/coroutines/ResourceExtension.kt https://github.com/kotest/kotest-extensions-arrow/pull/189#discussion_r909334682 :
+public class ResourceExtension(
Hey @Kantis https://github.com/Kantis,
Thanks for the review and remarks!
The user will always want to interact with A directly, the problem is that install does not support suspend which means it's only safe to access from within TestScope.
I tried to model it in such a way that it's impossible to access it from a non-suspend context, this would then be within the init block. Otherwise we'd have to implicitly use runBlocking under the hood to initialise the Resource, which are in a lot of cases doing blocking I/O, etc.
IIRC ResourceExtension<A, A> : MountableExtension<A, A> would not have this same guarantees in terms of preventing the users to access the A from outside of its initialised state.
The tests here are not a good representation of how it would actually be used in reality, since to tests this I have to expose an "unsafe resource" so we can verify the interactions/state. Normally domain code would expose something like Resource
and then the user would install, and use it like so: fun database(config: HikariConfig): Resource
= resource { val hikari = Resource.fromCloseable { HikariDataSource(config) }.bind() Resource({ Database.connect(hikari) }, { db, _ -> db.close() }).bind() } class MySpec : StringSpec({ val testDb = install(database(config).extension()) { configure() } // testDb.get() not allowed requires supension // runBlocking { testDb.get() } forcefully initialise anyway, while still respecting the
LifecycleMode
.beforeSpec { testDb.get() // allowed since this is supports suspension }
afterTest { testDb.get() // Also fine since it also supports suspension }
"test" { testDb().shouldNotBeNull() } })
— Reply to this email directly, view it on GitHub https://github.com/kotest/kotest-extensions-arrow/pull/189#discussion_r909334682, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFVSGUAP5NB7RMOBETJDRLVRQA23ANCNFSM5ZNRG2EA . You are receiving this because your review was requested.Message ID: @.***>
@sksamuel I think that would be really valuable.
Alternatively, can the Spec
init block become suspend
?
I assume the Kotest machinery that creates the classes are not within a suspending context?
It's because you can call it from the init constructor which isn't suspendable. So we just need to add a variant that is constrained to only be called inside a kotest callback or test. Should be easy enough to do - we can add a SuspendableExtension which plugins can use.
@i-walker @sksamuel @Kantis I updated this PR to use LazyMountableExtension
from 5.5.x
🥳
It could use another proper review now that the implementation has changed, I am not 100% sure I wired the XXListener
correctly. I wanted to support the same LifecycleMode
as Kotest has for TestContainerExtension
.
Thank you for the review Kantis! ❤️
This PR introduces an
MountableExtension
forResource
and aPerProjectListener
forResource
inspired by the Test Containers extensions. It also introducesTestResource
which we could expose in other ways.This all works on top of a combinator
allocatedCase
that I intend to introduce into Arrow Fx (Utils) as a sort of low-level operator to intro withResource
in ways like this.This would replace the
by resource
and the removal ofrunBlocking
used in there.