问题描述:

I am learning F# on my own and am trying to sneak some F# into the workplace.

As a result, I would like to write unit tests in F# to test C# logic.

Can anyone provide me a simple example of an F# unit test targeting a C# method and verifying a C# property as a result of exercising that method?

UPDATE:

Here's an example. When a value is provided for first and last name, how do we unit test (in F#) that GetFullName returns first and last name?

namespace MVVMExample

{

public class ViewModel : INotifyPropertyChanged

{

private string _firstName;

public string FirstName

{

get { return _firstName; }

set

{

_firstName = value;

RaisePropertyChanged("FirstName");

}

}

private string _lastName;

public string LastName

{

get { return _lastName; }

set

{

_lastName = value;

RaisePropertyChanged("LastName");

}

}

public string GetFullName()

{

return string.Format("{0} {1}", FirstName, LastName);

}

protected void RaisePropertyChanged(string propertyName)

{

PropertyChangedEventHandler handler = PropertyChanged;

if (handler != null)

{

handler(this, new PropertyChangedEventArgs(propertyName));

}

}

public event PropertyChangedEventHandler PropertyChanged;

}

}

网友答案:

So a very simple test for this ViewModel using NUnit could look like this:

testing GetFullName

here is a possible test for this function:

[<Test>]
member __.``GetFullName = "Jon Doe" if FirstName = "Jon" and LastName = "Doh"``() =
    let vm = ViewModel()
    vm.FirstName <- "Jon"
    vm.LastName <- "Doe"

    Assert.AreEqual("Jon Doe", vm.GetFullName())

testing PropertyChanged

[<TestFixture>]
type ``ViewModel Unit Tests``() = 

    [<Test>]
    member __.``a PropertyChanged event should be raised if the FirstName was changed``() =
        let vm = ViewModel()
        let mutable lastChangedProperty = ""
        vm.PropertyChanged.Add (fun e -> lastChangedProperty <- e.PropertyName)

        vm.FirstName <- "Tom"

        Assert.AreEqual("FirstName", lastChangedProperty)

Of course this is not really functional but I think it should be reasonable clear for the given problem.

as you can see it's basically the same you would expect from a C# test - the only F# feature I used are the function/class names in ``...`` which makes the output in your test-runner look nicer:

Code Walkthrough

  • the [TestFixture] class Test {...} just translates into [<TestFixture>] type Test() = ...
  • a [Test] method is just [<Test>] member this.MyTestFunction() = ... (this only if you need it - as you can see I did not so I used the idiomatic I-don't-care __ placeholder - see in F# you can name your this-reference any way you want - and you have to do it on each class-member.
  • as I want to change the lastChangedProperty string if the event is fired I declared it mutable (so you can use the assign operator <-)
  • to add an event-handler you can just use the .Addfunction on the event
  • (fun e -> ..) is an lambda - in C# this would be e => ...

disclaimer

of course if you want to use this viewmodel in say a WPF application you should make sure to dispatch to the UI-Thread, etc. which would make the test more nasty but for your example a simple red-green cycle should work ;)

I hope this helps you out (but of course it does not really show the advantages of F# as the test here is ugly side-effecty)

相关阅读:
Top