2

I'm using F# and Xunit. (I'm relatively new to both)

I've found that when I use Xunit's Assert.Equal() I need to specify "<string>" when the types being compared are string.

For example this run's and compiles:

[<Fact>]
let Test_XunitStringAssertion() =
    let s1 = "Stuff"
    Assert.Equal<string>("Stuff",s1)

My question is, why can't I remove "<string>" and just assert "Assert.Equal("Stuff",s1)" instead?

It looks to me like the compiler knows the types of both arguments, so why the fuss?

Here are the errors returned when compiling Assert.Equal("Stuff",s1):

error FS0041: A unique overload for method 'Equal' could not be determined based on type information prior to this program point. The available overloads are shown below (or in the Error List window). A type annotation may be needed.
error FS0041: Possible overload: 'Assert.Equal<'T>(expected: 'T, actual: 'T) : unit'.
error FS0041: Possible overload: 'Assert.Equal<'T>(expected: seq<'T>, actual: seq<'T>) : unit'.
error FS0041: Possible overload: 'Assert.Equal<'T>(expected: 'T, actual: 'T, comparer: System.Collections.Generic.IEqualityComparer<'T>) : unit'.
error FS0041: Possible overload: 'Assert.Equal(expected: float, actual: float, precision: int) : unit'.
error FS0041: Possible overload: 'Assert.Equal(expected: decimal, actual: decimal, precision: int) : unit'.
error FS0041: Possible overload: 'Assert.Equal<'T>(expected: seq<'T>, actual: seq<'T>, comparer: System.Collections.Generic.IEqualityComparer<'T>) : unit'.
Robert Patterson
  • 509
  • 7
  • 12
  • related: http://stackoverflow.com/questions/5667372/what-unit-testing-frameworks-are-available-for-f/5669263#5669263 (i.e. idiomatic F# assertions that are dramatically underpublicised) – Ruben Bartelink Feb 11 '14 at 21:24

2 Answers2

4

That's because string can be matched by both the first and second overloads (remember: string :> seq<char>).

Ramon Snir
  • 7,520
  • 3
  • 43
  • 61
4

Your example with <string> removed runs without error for me as I'd expect (although string :> seq<char> as @Ramon Snir points out, the overload resolution algorithm resolves the ambiguity by recognizing that the supplied string types are "closer" to string than seq<char>).

[<Fact>]
let Test_XunitStringAssertion() =
    let s1 = "Stuff"
    Assert.Equal("Stuff",s1)

I guess the sample you provided is not exactly the same as the real code which is causing you problems. Maybe s1 in your real code is not actually a string (or at least the compiler doesn't know it is).

Mathias
  • 15,191
  • 9
  • 60
  • 92
Stephen Swensen
  • 22,107
  • 9
  • 81
  • 136