F# SAFE- convert System.Threading.Tasks.Task<Result<int,exn>>' to 'Result<int,exn>'

I’m trying to write tests for my SAFE project, that is using SATURN in back end. In the test functions, I’m using Expect, and trying to match the return of my database with some expected results, but I can’t figure out how should i do this. I’ve tried this:

testCase "Add valid Book" <| fun _ ->
    let myProvisoryBook = {id="2"; title="A tilte"; author="an author"}
    let connection = new SqliteConnection(connectionString)
    let insertResult = Books.Database.insert connectionString myProvisoryBook 
    let expectedResult = Ok ()
    Expect.equal insertResult expectedResult "Result should be ok"


This expression was expected to have type
but here has type

What am I doing wrong? How can I do this tests in the correct way?

It looks like insertResult is a Task<Result<int,exn>. You should do insertResult.Result to access the result of the task. You should only do this in test code, not production code, because it will block the thread and you lose the benefit of using a task in the first place.

That takes care of the task part. The other issue is that insertResult has an int which you are trying to compare to unit. If you don’t care about the value inside the Ok then use this:

Expect.isOk insertResult.Result "Result should be ok"
1 Like

Thanks, It works. But, when I do insertResult.Result, what I’m doing is executing the task, and transforming it in a Result<int,exv> right?

When I do this, am I breaking some functional principle? And if I use:
|> Async.AwaitTask |>Async.RunSynchronously |> ignore
the async task will block in this line, in the same way, rigth?

It’s not breaking a functional principle. The same thing would be considered bad in C# code. Normally in some other application (e.g. a web server) you would pass the task back to your framework (e.g. ASP.NET Core) and some low level code would execute the task without blocking a thread, helping performance.

In a test it’s usually not considered a problem. However, I’ve just noticed there is a testCaseAsync function that you could use if you want to avoid blocking threads in your tests too.

And yes, |> Async.AwaitTask |> Async.RunSynchronously is effectively the same thing as .Result, so it’s no better.

1 Like