-
Notifications
You must be signed in to change notification settings - Fork 162
XUnit Property attribute respects IAsyncLifetime #703
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
3da73e8 to
ec851e2
Compare
| match testInstance with | ||
| | :? IAsyncLifetime as asyncLifetime -> asyncLifetime.InitializeAsync() | ||
| | _ -> Task.CompletedTask | ||
| |> ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.