fsprojects / FsUnit

FsUnit makes unit-testing with F# more enjoyable. It adds a special syntax to your favorite .NET testing framework.
http://fsprojects.github.io/FsUnit/
MIT License
425 stars 79 forks source link

[NUnit] Non provided generics is inferred to `obj` making test fails #274

Open MangelMaxime opened 4 months ago

MangelMaxime commented 4 months ago

Description

I am testing an API which returns Result<'Success, 'Error>, my problem is that type inference is not fully propagating to the type making it resolved the unknown generic to obj instead of the correct type.

CleanShot 2024-04-26 at 17 02 15

This makes the tests fails, and the cause of the failure is not obvious when looking at the message:

A total of 1 test files matched the specified pattern.
  Failed fails [42 ms]
  Error Message:
     Assert.That(, )
  Expected: Ok { Type = "feat" } or Ok { Type = "feat" }
  But was:  Ok { Type = "feat" }

  Stack Trace:
     at FsUnit.TopLevelOperators.should[a,a](FSharpFunc`2 f, a x, Object actual)
   at Parser.validateFirstLine.fails() in /Users/mmangel/Workspaces/Github/easybuild-org/commit-linter/tests/Parser.fs:line 16

1)    at FsUnit.TopLevelOperators.should[a,a](FSharpFunc`2 f, a x, Object actual)
   at Parser.validateFirstLine.fails() in /Users/mmangel/Workspaces/Github/easybuild-org/commit-linter/tests/Parser.fs:line 16

Failed!  - Failed:     1, Passed:     0, Skipped:     0, Total:     1, Duration: 42 ms - EasyBuild.CommitLinter.Tests.dll (net8.0)

Repro steps

module Parser

open NUnit.Framework
open FsUnit
open CommitLinter

module validateFirstLine =

    type CommitMessage = { Type: string }

    let expectedTyped: Result<_, string> = { Type = "feat" } |> Ok

    [<Test>]
    let fails () =
        { Type = "feat" } |> Ok
        |> should equal expectedTyped

Expected behavior

The test should pass.

Actual behavior

Test is failing

Known workarounds

If you enforce the type then the test pass:

module validateFirstLine =

    type CommitMessage = { Type: string }

    let expectedTyped: Result<_, string> = { Type = "feat" } |> Ok

    [<Test>]
    let fails () =
        ({ Type = "feat" } |> Ok : Result<CommitMessage, string>) // See that here I am forcing the type resolution
        |> should equal expectedTyped

Related information

CaptnCodr commented 3 months ago

Hi @MangelMaxime, sorry for the delay.

I have no solution for you. We already had those issues with type inference in previous issues ( https://github.com/fsprojects/FsUnit/issues/189 , https://github.com/fsprojects/FsUnit/issues/198 ). I would have suggested what you already encountered and provided in "Known workaround".

Have a wonderful day.

MangelMaxime commented 3 months ago

Hello @CaptnCodr,

If you think there is no solution or way to warn about it then we can close this issue.