XUnit Property attribute respects IAsyncLifetime#703
XUnit Property attribute respects IAsyncLifetime#703kurtschelfthout merged 2 commits intofscheck:masterfrom
Conversation
3da73e8 to
ec851e2
Compare
| match testInstance with | ||
| | :? IAsyncLifetime as asyncLifetime -> asyncLifetime.InitializeAsync() | ||
| | _ -> Task.CompletedTask | ||
| |> ignore |
There was a problem hiding this comment.
Don't we need to wait for the Task to complete? I think this will just start the task and your test is really fast so works, but for longer tasks it may show a problem.
E.g. if you change the test below to include a await Task.Delay(500) and only then set executed, does it still work?
There was a problem hiding this comment.
Of course, yes we need to wait. And the test is green only because it's a bad test: it checks whether InitializeAsync is invoked, not if its Task is completed. My bad. I'm on it to fix it.
Thank you for catching the problem.
There was a problem hiding this comment.
I confirm your doubt: the following test is red
type Issue657() =
let mutable executed = false;
interface IAsyncLifetime with
member _.InitializeAsync() =
async {
do! Async.Sleep 200
executed <- true
return ()
} |> Async.StartAsTask :> Task
member _.DisposeAsync() = Task.CompletedTask
[<Property>]
member this.``then InitializeAsync() is invoked``() =
executed = true|
I got to the conclusion that I would put the invocation right before invoking the test method, at Line 590 in 4f3f865 I thought that the following could work, but apparently I'm wrong: let invokeAndThrowInner (m:MethodInfo) o =
try
match target with
| Some (:? IAsyncLifetime as asyncLifetime) -> asyncLifetime.InitializeAsync()
| _ -> Task.CompletedTask
|> Async.AwaitTask
|> Async.StartAsTask
|> ignore
Reflect.invokeMethod m target o
with :? TargetInvocationException as e ->
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(e.InnerException).Throw() |
ae97a10 to
6c01dc7
Compare
|
I manage to have the test passing. match target with
| Some (:? IAsyncLifetime as asyncLifetime) -> asyncLifetime.InitializeAsync()
| _ -> Task.CompletedTask
|> Async.AwaitTask
|> Async.StartAsTask
|> Task.WaitAllI am not convinced of the last Before, I mentioned that the method could be invoked in |
6c01dc7 to
29f158d
Compare
|
Look great, thanks!
No - the test can still start tasks as normal. The
Right, definitely don't want that. |
Here's an attempt to fix #657.
This is my first change to FsCheck code, so I will surely need a good helping hand.
The change is few lines of code:
PropertyAttribute), it checks whether the test class implementsIAsyncLifetime.InitializeAsync()The PR includes a test, based on the sample code I proposed in #657 (comment)
Please, notice that
DisposeAsyncis not invoked. Apparently, neither xUnit invokes it. I am not sure if this is the correct behavior, though.