32
Unit Testing with Foq @ptrelford on @c4fsharp March 2013 Go download on Nuget or foq.codeplex.com

Unit Testing with Foq

Embed Size (px)

Citation preview

Page 1: Unit Testing with Foq

Unit Testing with Foq@ptrelford on @c4fsharp March 2013

Go download on Nuget or foq.codeplex.com

Page 2: Unit Testing with Foq

Testing Language

Page 3: Unit Testing with Foq

A Language for Testing

what should a language for writing

acceptance tests be?

Page 4: Unit Testing with Foq

A Language for Testing

Tests operate by example

they describe specific

scenarios and responses

Page 5: Unit Testing with Foq

A Language for Testing

I wonder if a different kind of

programming language

is required.- Martin Fowler 2003

Page 6: Unit Testing with Foq

UNIT TESTING WITH F#F# as a Testing Language

Page 7: Unit Testing with Foq

NUnit

F# NUnitmodule MathTest =

open NUnit.Framework

let [<Test>] ``2 + 2 should equal 4``() = Assert.AreEqual(2 + 2, 4)

C# NUnitusing NUnit.Framework;

[TestFixture]public class MathTest{ [Test] public void TwoPlusTwoShouldEqualFour() { Assert.AreEqual(2 + 2, 4); }}

Page 8: Unit Testing with Foq

FsUnit

let [<Test>] ``2 + 2 should equal 4``() = 2 + 2 |> should equal 4

Page 9: Unit Testing with Foq

Unquote

let [<Test>] ``2 + 2 should equal 4``() = test <@ 2 + 2 = 4 @>

Page 10: Unit Testing with Foq

.NET MOCKINGF# as a Testing Language

Page 11: Unit Testing with Foq

Mocking libraries

Page 12: Unit Testing with Foq

unittesting

Page 13: Unit Testing with Foq

Moq

var mock = new Mock<ILoveThisFramework>();

// WOW! No record/replay weirdness?! :)mock.Setup(framework => framework.DownloadExists("2.0.0.0")) .Returns(true) .AtMostOnce();

// Hand mock.Object as a collaborator and exercise it, // like calling methods on it...ILoveThisFramework lovable = mock.Object;bool download = lovable.DownloadExists("2.0.0.0");

// Verify that the given method was indeed called with the expected valuemock.Verify(framework => framework.DownloadExists("2.0.0.0"));

Page 14: Unit Testing with Foq

FakeItEasy

// Creating a fake object is just dead easy!// No mocks, no stubs, everything's a fake!var lollipop = A.Fake<ICandy>();var shop = A.Fake<ICandyShop>();

// To set up a call to return a value is also simple:A.CallTo(() => shop.GetTopSellingCandy()).Returns(lollipop);

// Use your fake as you would an actual instance of the faked type.var developer = new SweetTooth();developer.BuyTastiestCandy(shop);

// Asserting uses the exact same syntax as when configuring calls,// no need to teach yourself another syntax.A.CallTo(() => shop.BuyCandy(lollipop)).MustHaveHappened();

Page 15: Unit Testing with Foq

F# Object Expressions

Mock objectMock<IShopDataAccess>() .Setup(fun data -> <@ data.GetProductPrice(any()) @>) .Calls<int>(function | 1234 -> 45M | 2345 -> 15M | productID -> failwith "Unexpected" ) .Create()

Object Expression{ new IShopDataAccess with member __.GetProductPrice(productId) = match productId with | 1234 -> 45M | 2345 -> 15M | _ -> failwith "Unexpected" member __.Save(_,_) = failwith "Not implemented"}

Page 16: Unit Testing with Foq

FOQ MOCKINGF# as a Testing Language

Page 17: Unit Testing with Foq

WTF

Page 18: Unit Testing with Foq

Foq: IList<char>

// Arrangelet xs = Mock<IList<char>>.With(fun xs -> <@ xs.Count --> 2 xs.Item(0) --> '0' xs.Item(1) --> '1' xs.Contains(any()) --> true xs.RemoveAt(2) ==> System.ArgumentOutOfRangeException() @> )// AssertAssert.AreEqual(2, xs.Count)Assert.AreEqual('0', xs.Item(0))Assert.AreEqual('1', xs.Item(1))Assert.IsTrue(xs.Contains('0'))Assert.Throws<System.ArgumentOutOfRangeException>(fun () -> xs.RemoveAt(2))

Page 19: Unit Testing with Foq

Foq: Anonymous Type

var order = new Mock<IOrder>() .SetupProperties(new { Price = 99.99M, Quantity = 10, Side = Side.Bid, TimeInForce = TimeInForce.GoodTillCancel }) .Create();Assert.AreEqual(99.99M, order.Price);Assert.AreEqual(10, order.Quantity);Assert.AreEqual(Side.Bid, order.Side);Assert.AreEqual(TimeInForce.GoodTillCancel, order.TimeInForce);

Page 20: Unit Testing with Foq

Foq: Type Inference

let [<Test>] ``order sends mail if unfilled`` () = // setup data let order = Order("TALISKER", 51) let mailer = mock() order.SetMailer(mailer) // exercise order.Fill(mock()) // verify verify <@ mailer.Send(any()) @> once

Page 21: Unit Testing with Foq

Foq Sequences

let [<Test>] ``verify sequence of calls`` () = // Arrange let xs = Mock.Of<IList<int>>() // Act xs.Clear() xs.Add(1) // Assert Mock.VerifySequence <@ xs.Clear() xs.Add(any()) @>

Page 22: Unit Testing with Foq

FOQ DEPLOYMENTF# as a Testing language

Page 23: Unit Testing with Foq

Deployment

Nuget DowloadCodePlex Download

Page 24: Unit Testing with Foq

FOQ APIF# as a testing language

Page 25: Unit Testing with Foq

LINQ or Quotations

Setup a mock method in C# with a lambda expression:

new Mock<IList<int>>()

.Setup(x => x.Contains(It.IsAny<int>())).Returns(true)

.Create();

Setup a mock method in F# with a Code Quotation:

Mock<System.Collections.IList>()

.Setup(fun x -> <@ x.Contains(any()) @>).Returns(true)

.Create()

Page 26: Unit Testing with Foq

Fluent Interface orFunctions

Page 27: Unit Testing with Foq

FOQ IMPLEMENTATIONF# as a testing language

Page 28: Unit Testing with Foq

LOC: Moq vs FakeItEasy

Moq

Total 16454

{ or } 2481

Blank 1933

Null checks 163

Comments 7426

Useful lines 4451

FakeItEasy

Total 11550

{ or } 2948

Blank 1522

Null checks 92

Comments 2566

Useful lines 4422

Page 29: Unit Testing with Foq

Fock (aka Foq)

Fock v0.1

127 Lines• Interfaces• Methods• Properties

Fock v0.2

200 Lines• Interfaces• Abstract Classes• Methods• Properties• Raise Exceptions

Page 30: Unit Testing with Foq

LOC: Foq 0.8.1

Foq.fs

Total 666

Foq.fs + Foq.Linq.fs

Total 933

Page 31: Unit Testing with Foq

QUESTIONSF# as a Testing Language

Page 32: Unit Testing with Foq

What The Foq?