F# is a cool and exciting language. It’s much more than an academic language; it can solve many real life (coding) problems in its functional manner. As to production code, it must be covered with unit tests. I’ll show a simple example of a unit test written in C# with moq against F# code.
The code under test is a simple lottery calculator: it takes a list of participants and says how much every participant won – 5 times the number of hits. Simple, isn’t it?
Let’s take a look at the code under test, it could probably be written better, but ignore this for now 🙂
type LotteryCalculator(winningNumbers:System.Collections.Generic.IList) =
let calculatePrize(participatingNumbers) =
let numOfHits = participatingNumbers |>
Seq.filter (fun participatingNumber -> winningNumbers.Contains participatingNumber) |>
Set.ofSeq |>
Set.count
numOfHits * 5
member this.CalculatePrizes(participants:System.Collections.Generic.IEnumerable) =
participants
|> Seq.map (fun participant -> (participant, calculatePrize(participant.GetTicket())))
So, we have an API method, CalculatePrizes(), which take a collection of participants, look at their tickets and returns a tuples list of participant and prize. So we have something like this: CalculatePrizes: System.Collections.Generic.IEnumerable –> seq
After dealing with some issues, which I’ll write about in a future post, I wrote this test:
[Test]
public void CalculatePrizes_RecievesTwoParticipant_MatchCorrectPrizes()
{
var firstParticipantMock = new Moq.Mock<IParticipant>();
IParticipant firstParticipant = firstParticipantMock.Object;
firstParticipantMock.Setup(fake => fake.GetTicket()).Returns(new List<int> {1, 4, 5});
var secondParticipantMock = new Moq.Mock<IParticipant>();
IParticipant secondParticipant = secondParticipantMock.Object;
secondParticipantMock.Setup(fake => fake.GetTicket()).Returns(new List<int> { 1, 2, 4 });
var lotteryCalculator = new LotteryCalculator(new List<int> {1, 2, 3});
var participantPrizes = lotteryCalculator.CalculatePrizes(new[] { firstParticipant, secondParticipant });
var prizes = participantPrizes.ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
Assert.That(prizes[firstParticipant], Is.EqualTo(5));
Assert.That(prizes[secondParticipant], Is.EqualTo(10));
}
It’s nice that we can keep our unit tests written in C#, it’s also important in cases where the users of the code (most likely us in another module) will use it in C# as well.