I have a test where a json with a number is deserialized, then serialized, then both jsons (original an deserialized-serialized) are compared for string equality. The project is built for net8.0 and net48/481.
When using dotnet test
, I get the following results:
5.32
becomes 5.32
.5.32
becomes 5.3200000000000003
.When using the little Run Test
button in VScode
I MOSTLY get a pass, but sometimes a fail (for the same number-related reason). In that case, closing VSCode, closing all dotnet.exe
background processes, then reopening VScode resolves the issue usually. Unfortunately, I don't know a way to relaibly reproduce this issue.
Questions:
dotnet test
?Run Test
button sometimes give different results?Here are project file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0-windows;net481;net48</TargetFrameworks>
<LangVersion>10.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" />
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" />
<PackageReference Include="coverlet.collector" Version="3.1.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net48' Or '$(TargetFramework)' == 'net481'">
<PackageReference Include="System.Text.Json" Version="8.0.4" />
</ItemGroup>
</Project>
and test file
using System.Text.Json;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class NumberSerializingTests
{
[TestMethod]
public void TestNumberSerializing()
{
var json = "{\"Number\":5.32}";
var data = JsonSerializer.Deserialize<MyNumber>("{\"Number\":5.32}");
var json2 = JsonSerializer.Serialize(data);
Assert.AreEqual(json, json2);
}
}
public class MyNumber
{
public MyNumber(double number) { Number = number; }
public double Number { get; }
}
The fix for your requirements is simple:
public MyNumber(decimal number) { Number = number; }
public decimal Number { get; }
The reasons are covered in mine/Panagiotis's comments.