最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

types - F# testing using mstest cannot resolve method overload - Stack Overflow

programmeradmin6浏览0评论

As a learning exercise, I'm trying to test some F# code using MSTEST. I've run into a problem that is driving me crazy, not because I can't work around it, but because I don't understand how to properly add a type annotation to determine what overloaded method I'm using (meaning I haven't properly learned what I'm trying to learn).

Anyway, here is a simplified example of the non-working code:

[<TestClass>]
type MyTests () =

    [<TestMethod>]
    member this.SyntaxTest () =
        Assert.AreEqual<bool>(true, false)  // compiles                    
        Assert.AreEqual<bool>(expected=true, actual=false) // compiles
        Assert.AreEqual<bool>((true : bool), (false : bool))  // compiles
        Assert.AreEqual<bool>(true, false, "message string") // fails to compile
        Assert.AreEqual<bool>(true, false, ("message string" : string)) // fails to compile
        Assert.AreEqual<bool>(expected=true, actual=false, message="message string") // fails to compile

        // Simple work around that doesn't answer how to properly make the Assert.AreEqual call:
        if (true <> false) then do
            Assert.Fail("Fail message")
 

As can be seen in the comments, the version using only bool inputs works fine using several different versions of type and parameter notations. However, as soon as I add a message string, nothing I can think of to do will make it compile.

The fail code I get is:

FS0041: A unique overload for method 'AreEqual' could not be determined based on type information prior to this program point. A type annotation may be needed. Known types of arguments: bool * bool * string Candidates: - Assert.AreEqual<'T>(expected: 'T | null, actual: 'T | null, message: string | null) : unit - Assert.AreEqual<'T>(expected: 'T | null, actual: 'T | null, message: string | null, [] parameters: obj | null array | null) : unit ....

From the Microsoft documentation link there are an awful lot of different Assert.AreEqual methods with slightly different signatures, but I apparently have no idea how to tell the F# compiler which one I want. From what I've read, I thought that adding ":string" or "message=" might help, but it doesn't.

Does anyone know how to get the compiler to properly resolve the method overload issue? Also, if anyone can link to a definitive resource for this issue, that would be amazing!

As a learning exercise, I'm trying to test some F# code using MSTEST. I've run into a problem that is driving me crazy, not because I can't work around it, but because I don't understand how to properly add a type annotation to determine what overloaded method I'm using (meaning I haven't properly learned what I'm trying to learn).

Anyway, here is a simplified example of the non-working code:

[<TestClass>]
type MyTests () =

    [<TestMethod>]
    member this.SyntaxTest () =
        Assert.AreEqual<bool>(true, false)  // compiles                    
        Assert.AreEqual<bool>(expected=true, actual=false) // compiles
        Assert.AreEqual<bool>((true : bool), (false : bool))  // compiles
        Assert.AreEqual<bool>(true, false, "message string") // fails to compile
        Assert.AreEqual<bool>(true, false, ("message string" : string)) // fails to compile
        Assert.AreEqual<bool>(expected=true, actual=false, message="message string") // fails to compile

        // Simple work around that doesn't answer how to properly make the Assert.AreEqual call:
        if (true <> false) then do
            Assert.Fail("Fail message")
 

As can be seen in the comments, the version using only bool inputs works fine using several different versions of type and parameter notations. However, as soon as I add a message string, nothing I can think of to do will make it compile.

The fail code I get is:

FS0041: A unique overload for method 'AreEqual' could not be determined based on type information prior to this program point. A type annotation may be needed. Known types of arguments: bool * bool * string Candidates: - Assert.AreEqual<'T>(expected: 'T | null, actual: 'T | null, message: string | null) : unit - Assert.AreEqual<'T>(expected: 'T | null, actual: 'T | null, message: string | null, [] parameters: obj | null array | null) : unit ....

From the Microsoft documentation link there are an awful lot of different Assert.AreEqual methods with slightly different signatures, but I apparently have no idea how to tell the F# compiler which one I want. From what I've read, I thought that adding ":string" or "message=" might help, but it doesn't.

Does anyone know how to get the compiler to properly resolve the method overload issue? Also, if anyone can link to a definitive resource for this issue, that would be amazing!

Share Improve this question asked Mar 17 at 4:46 John Christopher LinstrumJohn Christopher Linstrum 4551 gold badge6 silver badges11 bronze badges 1
  • related: It can be argued that the idiomatic way to write tests in F# is unquote (I use it with xunit, but it works with any test framework and does not go down the road of depending on a Fluent Assertions library!) stackoverflow/a/5669263/11635 – Ruben Bartelink Commented Mar 18 at 11:16
Add a comment  | 

1 Answer 1

Reset to default 2

Unfortuanately, this testing framework was written with only C# in mind, which means that the method overload you're trying to call expects "nullable" types:

void AreEqual<T>(T? expected, T? actual, string? message)

(Nullable types are a truly hideous feature of C# that they've had to introduce because null values are so common in that language, but I digress.)

So, to help F# find the correct overload, you have to explicitly make your values nullable:

open System
...

Assert.AreEqual(Nullable true, Nullable false, "message string")

The silver lining in this ugly cloud is that you can at least leave off the explicit <Nullable<bool>> type argument, because F# will infer that for you.

As a workaround, if this is something you need to call often, you could also define your own AreEqual member:

type Assert with
    static member inline AreEqual(expected : bool, actual : bool, message : string) =
        Assert.AreEqual(Nullable expected, Nullable actual, message)

And then you can call it normally:

Assert.AreEqual(true, false, "message string")
发布评论

评论列表(0)

  1. 暂无评论