On Tuesday I did a lightning talk at the MVP Summit in Bellevue on connecting to all things, from statistics to statistical programming languages with Intellisense and LINQ using F# Type Providers, a feature shipped with Visual Studio 2012:
Connecting to an Excel file:
Querying users stored on SQL Azure:
query {
for u in db.Users do
where (u.UserId <> userId)
select u
}
Querying genres via the Netflix API:
query {
for g in ctx.Genres do
where (g.Name = genre)
for t in g.Titles do
where (t.ReleaseYear ?<= 1959)
where (t.ReleaseYear ?>= 1934)
sortByNullable t.AverageRating
skip nToSkip
take nToTake
select t
}
Running B-Movie Sample on Azure: b-movies.azurewebsites.net
Connecting to the World Bank:
type WorldBank = WorldBankDataProvider<"World Development Indicators">
let data = WorldBank.GetDataContext()
let countries () =
[| data.Countries.India
data.Countries.``United Kingdom``
data.Countries.``United States`` |]
Rendering charts asynchronously using JavaScript High Charts using TypeScript definitions:
let render () = async {
let opts = h.HighchartsOptions()
opts.chart <- h.HighchartsChartOptions(renderTo = "chart", ``type`` = "line")
opts.title <- h.HighchartsTitleOptions(text = "School enrollment")
Running in the browser using FunScript (F# to JavaScript compiler):
Querying Hadoop Hive in the browser:
query {
for i in hive.iris do
groupBy i.``class`` into g
select (g.Key, Seq.length g)
}
Foq is an open source .Net mocking library with a familiar fluent API for Moq users that lets you setup mock object using either LINQ or F# Code Quotations. Moq was developed to take advantage of .Net 3.5 LINQ expression trees and C# 3.0 features. Foq has been designed to provide first-class support for users of both C# and F#. C# users can use the LINQ API while F# users can choose between the LINQ API and Code Quotations. We use F# as a unit testing language at work and Foq for mocking code written in both C# and F#.
Examples
Setup a mock method in C# with a lambda expression:
new Mock<IList<int>>()
.SetupFunc(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()
Setup a property in C# with a lambda expression:
new Mock<IList<int>>()
.SetupPropertyGet(x => x.Count).Returns(1)
.Create();
Setup multiple properties in C# with an anonymous object:
new Mock<IOrder>()
.SetupProperties(new {
Price = 99.99M,
Quantity = 10,
Side = Side.Bid,
TimeInForce = TimeInForce.GoodTillCancel
})
.Create();
Setup multiple members in F# with a Code Quotation:
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()
@>
)
Verify a method was called in C#:
Mock.VerifyFunc(() => list.Contains(1));
Verify a method was called once in F#:
Mock.Verify(<@ xs.Contains(any()) @>, once)
Download
Foq is available on Nuget or for F# projects you can just include the Foq.fs source file.
F# 3 has LINQ expression support built-in just like C# and VB.Net. Prior to this basic LINQ expression interop could be achieved with the F# PowerPack and F# Code Quotations.
F# 3 LINQ support opens up APIs that use LINQ expressions like Moq, a popular .Net mocking library. With some minor workarounds Moq is relatively easy to call from F#.
C# Moq example:
var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
F# requires a type annotation:
F# requires the return value to be explicitly ignored:
F# Moq example with required type annotation and return value piped to ignore:
let mock = Mock<IFoo>()
mock.Setup<bool>(fun foo -> foo.DoSomething("ping")).Returns(true) |> ignore
The type annotation is required as the Setup method provides multiple overloads with differing generic parameters. Another way to workaround this is to write specific extension methods for overloads:
type Moq.Mock<'T> when 'T : not struct with
/// Specifies a setup on the mocked type for a call to a function
member mock.SetupFunc<'TResult>(expression:Expression<Func<'T,'TResult>>) =
mock.Setup<'TResult>(expression)
/// Specifies a setup on the mocked type for a call to a void method
member mock.SetupAction(expression:Expression<Action<'T>>) =
mock.Setup(expression)
/// Specifies a setup on the mocked type for a call to a property setter
member mock.SetupSetAction<'TProperty>(setupExpression:Action<'T>)
: Moq.Language.Flow.ISetupSetter<'T,'TProperty> =
mock.SetupSet<'TProperty>(setupExpression)
The ignore statement is required as F# requires return values to be handled explicitly. Moq’s fluent inteface provides some methods where the return value is ignorable.
The issues using Moq’s API from F# 3 can be fairly easily worked around. That said for an API designed specifically for F# consider using Foq which has similar functionality to Moq and supports both Code Quotations and LINQ expressions. You may also find F#’s built-in Object Expressions sufficient for many tasks.