Closed abushnaq-work closed 1 year ago
Did I maybe misunderstand and this https://github.com/Quick/Nimble/pull/1007/ is not in 11.1 but will be in a later version?
My apologies for the poor wording. I struggled with how to correctly word that message.
Prepend await
to the entire expression. For example: await expect(blah).toEventually(...)
.
Hi and thank you for the quick answer,
It seems to be required to run on the main thread? It's tripping an assertion on Nimble/PostNotification.swift:64: Assertion failed: Only expecting closure to be evaluated on main thread.
.
This is my first project with async/await so I'm a bit shaky. I tried surrounding that with MainActor.run
to ensure it runs on the main thread:
MainActor.run
{
let notification = Notification(name: Constants.BadJSONNotification)
await expect {
await expect(await provisioningManager.processFeatures(emptyJSON)).to(beFalse())
}.toEventually(postNotifications(equal([notification])))
}
But that triggers a compile error Cannot pass function of type '@Sendable () async -> ()' to parameter expecting synchronous function type
.
Part of me wants to tag everything with await up the chain, but that doesn't make sense as I earlier had await expect(await provisioningManager.processJSON(badJSON).to(beFalse())
and it worked fine without tagging more items up the chain as async.
Oh. I'm sorry. I misunderstood what you were doing. This is confusing, and I'm sorry.
As of Nimble 11, toEventually does not work async Expressions. That is, expect { await someAsyncFunction() }.toEventually(...)
is not supported and will not compile. In this case, Expression is the value or closure passed in to expect
.
toEventually
works using a polling mechanism - it runs the Expression (the value or closure passed in to expect
) many times until the matcher passes. In Nimble 11, the way async Expressions are supported is a bit of a hack that I bolted on to Nimble's existing infrastructure; Nimble await
s the async Expression, then uses the resulting value with the existing, synchronous, infrastructure. This approach is fundamentally incompatible with toEventually
's approach of re-running the Expression every pollInterval: all that would happen is it would test the same value it received previously.
I would like to fix this, but I've yet to come up with a good solution for all of the problems introduced by it.
Again, I'm really sorry for this confusion.
No worries I appreciated the detailed and patient explanation. So there's currently no way to test an async function for notifications then - is that right?
Maybe I can look into XCTest for that part and have Nimble do everything else. I appreciate all the work done in Nimble - this is my second project with it and it just makes sense. :)
So there's currently no way to test an async function for notifications then - is that right?
That's correct. You could certainly cobble together something yourself that does it, but Nimble doesn't provide anything out of the box for this.
I created https://github.com/Quick/Nimble/issues/1013 to specifically track this issue (and in general other wonkiness with the approach I took when implementing Async support for expectations).
Got it, thanks for your help.
What did you do?
Added code trying to test for a notification being fired in an async context:
let notification = Notification(name: Constants.BadJSONNotification) expect { await expect(await provisioningManager.processJSON(badJSON).to(beFalse()) }.toEventually(postNotifications(equal([notification])))
What did you expect to happen?
Initially expected it to work. I got the warning:
Instance method 'toEventually' is unavailable from asynchronous contexts; the sync version of
toEventuallydoes not work in async contexts. Use the async version with the same name as a drop-in replacement; this is an error in Swift 6
and have so far completely failed to find the async version
What actually happened instead?
I have completely failed to either find an example, documentation, or the definition of the aforementioned async version.
Environment
List the software versions you're using:
Xcode Default
.)Please also mention which package manager you used and its version. Delete the other package managers in this list:
Project that demonstrates the issue
Nothing to demonstrate just hopefully someone can point me to the right place if this is supported.