Search code examples
f#initializationxunit

F#: how to have the variables defined above a XUnit test function actually initialized when running the test?


Following up another question: F#: Why those two collections are not equal? the example below shows that when running Open an account... test id and contact are not initialized.

If there were functions returning the same values and called in the test body it would work though.

I am wondering why this is case, and if there is anything I can do to have those variables properly initialized when the test is running.

let id = Guid.Empty
let contact = {
    Name = {
        FirstName = "Marcel"
        MiddleInitial = None
        LastName = "Patulacci"
    }
    DateOfBith = new DateTime(1850, 12, 25)
    Address = {
        Address1 = "41 av 8 Mai 1945"
        Address2 = None
        City = "Sarcelles"
        State = None
        Zip = "95200"
    }
    PhoneNumber = {
        DialOutCode = 33
        LocalNumber = "766030703"
    }
    Email = "[email protected]"
}

[<Fact>]
let ``Open an account...``() =
    let event = Event.AccountOpened({
        AccountId = id
        Contact = contact
    })

    let a = [event]
    let b = seq { yield event }

    Assert.Equal(a, b)

Solution

  • This is down to how F# modules are implemented in .NET IL. Modules are compiled into static classes, and module-defined values are initialized in the class's static constructor. But because of the way XUnit loads tests, the static constructor is not run.

    A possible way to circumvent this is to use a class instead of a module, as XUnit does run instance constructors. let functions in a class are compiled to private methods, so the tests are recognized by XUnit without having to switch to member syntax.

    type MyTests() =
    
        let id = Guid.Empty
        let contact = // ...
    
        [<Fact>]
        let ``Open an account...``() =
            // ...