Ok, spent some time debugging the runner itself.
It seems that the issue Rewrite.fs file, fsharp-test-runner/src/Exercism.TestRunner.FSharp/Rewrite.fs at main · exercism/fsharp-test-runner · GitHub this line more precisely.
After the rewrite happens, the output of the test code is the following. So every " inside the string is escaped with additional \, that makes the json invalid.
And all tests start to fail with the error about the incorrect json format.
Here is the Rider output for one of the tests:
System.Text.Json.JsonException: '\' is an invalid start of a property name. Expected a '"'. Path: $ | LineNumber: 0 | BytePositionInLine: 1.
System.Text.Json.JsonException
'\' is an invalid start of a property name. Expected a '"'. Path: $ | LineNumber: 0 | BytePositionInLine: 1.
at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, JsonReaderException ex)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 utf8Json, JsonTypeInfo`1 jsonTypeInfo, Nullable`1 actualByteCount)
at System.Text.Json.JsonSerializer.ReadFromSpan[TValue](ReadOnlySpan`1 json, JsonTypeInfo`1 jsonTypeInfo)
at RestApi.RestApi..ctor(String database) in /Users/Rakkatakka/Exercism/fsharp/rest-api/RestApi.fs:line 37
at RestApiTests.Add user() in /Users/Rakkatakka/Exercism/fsharp/rest-api/RestApiTests.fs:line 24
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
System.Text.Json.JsonReaderException
'\' is an invalid start of a property name. Expected a '"'. LineNumber: 0 | BytePositionInLine: 1.
at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
at System.Text.Json.Utf8JsonReader.ReadSingleSegment()
at System.Text.Json.Utf8JsonReader.Read()
at System.Text.Json.Serialization.Converters.ObjectWithParameterizedConstructorConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value, Boolean& isPopulatedValue)
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
And here is the entire malformed test file.
module RestApiTests
open FsUnit.Xunit
open Xunit
open RestApi
[<Fact>]
let ``No users`` () =
let database = """{\\"users\\":[]}"""
let url = "/users"
let expected = """{\\"users\\":[]}"""
let api = RestApi(database)
api.Get url |> should equal expected
[<Fact>]
let ``Add user`` () =
let database = """{\\"users\\":[]}"""
let payload = """{\\"user\\":\\"Adam\\"}"""
let url = "/add"
let expected =
"""{\\"name\\":\\"Adam\\",\\"owes\\":{},\\"owed_by\\":{},\\"balance\\":0.0}"""
let api = RestApi(database)
api.Post(url, payload) |> should equal expected
[<Fact>]
let ``Get single user`` () =
let database =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{},\\"owed_by\\":{},\\"balance\\":0.0},{\\"name\\":\\"Bob\\",\\"owes\\":{},\\"owed_by\\":{},\\"balance\\":0.0}]}"""
let payload = """{\\"users\\":[\\"Bob\\"]}"""
let url = "/users"
let expected =
"""{\\"users\\":[{\\"name\\":\\"Bob\\",\\"owes\\":{},\\"owed_by\\":{},\\"balance\\":0.0}]}"""
let api = RestApi(database)
api.Get(url, payload) |> should equal expected
[<Fact>]
let ``Both users have 0 balance`` () =
let database =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{},\\"owed_by\\":{},\\"balance\\":0.0},{\\"name\\":\\"Bob\\",\\"owes\\":{},\\"owed_by\\":{},\\"balance\\":0.0}]}"""
let payload =
"""{\\"lender\\":\\"Adam\\",\\"borrower\\":\\"Bob\\",\\"amount\\":3.0}"""
let url = "/iou"
let expected =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{},\\"owed_by\\":{\\"Bob\\":3.0},\\"balance\\":3.0},{\\"name\\":\\"Bob\\",\\"owes\\":{\\"Adam\\":3.0},\\"owed_by\\":{},\\"balance\\":-3.0}]}"""
let api = RestApi(database)
api.Post(url, payload) |> should equal expected
[<Fact>]
let ``Borrower has negative balance`` () =
let database =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{},\\"owed_by\\":{},\\"balance\\":0.0},{\\"name\\":\\"Bob\\",\\"owes\\":{\\"Chuck\\":3.0},\\"owed_by\\":{},\\"balance\\":-3.0},{\\"name\\":\\"Chuck\\",\\"owes\\":{},\\"owed_by\\":{\\"Bob\\":3.0},\\"balance\\":3.0}]}"""
let payload =
"""{\\"lender\\":\\"Adam\\",\\"borrower\\":\\"Bob\\",\\"amount\\":3.0}"""
let url = "/iou"
let expected =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{},\\"owed_by\\":{\\"Bob\\":3.0},\\"balance\\":3.0},{\\"name\\":\\"Bob\\",\\"owes\\":{\\"Adam\\":3.0,\\"Chuck\\":3.0},\\"owed_by\\":{},\\"balance\\":-6.0}]}"""
let api = RestApi(database)
api.Post(url, payload) |> should equal expected
[<Fact>]
let ``Lender has negative balance`` () =
let database =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{},\\"owed_by\\":{},\\"balance\\":0.0},{\\"name\\":\\"Bob\\",\\"owes\\":{\\"Chuck\\":3.0},\\"owed_by\\":{},\\"balance\\":-3.0},{\\"name\\":\\"Chuck\\",\\"owes\\":{},\\"owed_by\\":{\\"Bob\\":3.0},\\"balance\\":3.0}]}"""
let payload =
"""{\\"lender\\":\\"Bob\\",\\"borrower\\":\\"Adam\\",\\"amount\\":3.0}"""
let url = "/iou"
let expected =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{\\"Bob\\":3.0},\\"owed_by\\":{},\\"balance\\":-3.0},{\\"name\\":\\"Bob\\",\\"owes\\":{\\"Chuck\\":3.0},\\"owed_by\\":{\\"Adam\\":3.0},\\"balance\\":0.0}]}"""
let api = RestApi(database)
api.Post(url, payload) |> should equal expected
[<Fact>]
let ``Lender owes borrower`` () =
let database =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{\\"Bob\\":3.0},\\"owed_by\\":{},\\"balance\\":-3.0},{\\"name\\":\\"Bob\\",\\"owes\\":{},\\"owed_by\\":{\\"Adam\\":3.0},\\"balance\\":3.0}]}"""
let payload =
"""{\\"lender\\":\\"Adam\\",\\"borrower\\":\\"Bob\\",\\"amount\\":2.0}"""
let url = "/iou"
let expected =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{\\"Bob\\":1.0},\\"owed_by\\":{},\\"balance\\":-1.0},{\\"name\\":\\"Bob\\",\\"owes\\":{},\\"owed_by\\":{\\"Adam\\":1.0},\\"balance\\":1.0}]}"""
let api = RestApi(database)
api.Post(url, payload) |> should equal expected
[<Fact>]
let ``Lender owes borrower less than new loan`` () =
let database =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{\\"Bob\\":3.0},\\"owed_by\\":{},\\"balance\\":-3.0},{\\"name\\":\\"Bob\\",\\"owes\\":{},\\"owed_by\\":{\\"Adam\\":3.0},\\"balance\\":3.0}]}"""
let payload =
"""{\\"lender\\":\\"Adam\\",\\"borrower\\":\\"Bob\\",\\"amount\\":4.0}"""
let url = "/iou"
let expected =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{},\\"owed_by\\":{\\"Bob\\":1.0},\\"balance\\":1.0},{\\"name\\":\\"Bob\\",\\"owes\\":{\\"Adam\\":1.0},\\"owed_by\\":{},\\"balance\\":-1.0}]}"""
let api = RestApi(database)
api.Post(url, payload) |> should equal expected
[<Fact>]
let ``Lender owes borrower same as new loan`` () =
let database =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{\\"Bob\\":3.0},\\"owed_by\\":{},\\"balance\\":-3.0},{\\"name\\":\\"Bob\\",\\"owes\\":{},\\"owed_by\\":{\\"Adam\\":3.0},\\"balance\\":3.0}]}"""
let payload =
"""{\\"lender\\":\\"Adam\\",\\"borrower\\":\\"Bob\\",\\"amount\\":3.0}"""
let url = "/iou"
let expected =
"""{\\"users\\":[{\\"name\\":\\"Adam\\",\\"owes\\":{},\\"owed_by\\":{},\\"balance\\":0.0},{\\"name\\":\\"Bob\\",\\"owes\\":{},\\"owed_by\\":{},\\"balance\\":0.0}]}"""
let api = RestApi(database)
api.Post(url, payload) |> should equal expected