F# 3 supports LINQ Expressions which makes Moq now relatively easy to use with F#:

1
2
let mock = Mock<IFoo>()
mock.Setup<bool>(fun foo -> foo.DoSomething("ping")).Returns(true) |> ignore

See Moq with F# 3

Phil

By on 1/27/2013 9:10 AM ()

Here is a sample code from the moq-Website ([link:code.google.com] in C#:

1
2
3
4
var mock = new Mock<IFoo><ifoo>();


mock.Expect(foo => foo.Execute("ping")).Returns(true);

My problem ist the part foo => foo.Execute("ping"), which is a LINQ Expression.

Can I get this in F#?

Best regards,

Steffen</ifoo>

By on 2/24/2009 7:00 AM ()

Hi,
You can access the method from F#. Unfortunately, F# doesn't convert its lambda functions into .NET delegates automatically, so you have to explicitly create the delegate (from F# function). I haven't tried that but something like this should work (assuming that the epxected type of the Expect method is .NET 3.5 Func):

1
2
 
mock.Expect(new Func<_, _>(fun foo -> foo.Execute("ping"))).Returns(true);

This is of course a bit ugly, but you can write an F# extension method that takes a function as an argument and does the wrapping for you:

1
2
3
4
5
6
7
8
9
 
module MyExtensions =
  type FullNamespaceOfTheMockType.Mock with // <- specify full namespace here
    member x.Expect(f) = 
      mock.Expect(new Func<_, _>(f))

// Now you should be able to write
open MyExtensions
mock.Expect(fun foo -> foo.Execute("ping")).Returns(true);

I haven't tried that, but something like this should do the trick!

By on 2/24/2009 8:00 AM ()

Thanks for the hint, but unfortunately he wants a System.Linq.Expressions.Expression<System.Func<IFoo,'a>>.
How can I get the expression - I don't see a constructor or somthing for it? This would be the last step.

Regards,
forki

By on 2/24/2009 9:13 AM ()

Ahh, I see!
That changes many things :-), but the important thing is that it should still be possible!
F# has a feature called quotations that allows you to do similar thing as C# expression trees. The representation of quotations is different than Expression<Func<...>>, but there is a function to convert quotations to expression trees.

You'll need to reference the FSharp.PowerPack.Linq.dll assembly first and then something like this should work:

1
2
3
4
5
6
7
 
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation // from PowerPack.Linq

let quot = <@ fun (foo:IFoo) => foo.Execute("ping") @> // create quotation
let expr = quot.ToLinqExpression() // convert to Expression<Func<...>>
mock.Expect(expr).Returns(true) // should now work!

Hope this helps!

By on 2/24/2009 9:29 AM ()

I am sorry, but I still don't get it working.

I have:

1
2
3
4
5
6
7
8
9
10
11
12
13
    

let f = fun (foo:IFoo) -> foo.Exceute("ping")


let func = new System.Func<_, _>(f)


let quot = <@ func @> // create quotation


let expr = quot.ToLinqExpression()

ToLinqExpression() has type System.Linq.Expressions.Expression but mock.Expect needs System.Linq.Expressions.Expression<System.Func<IFoo,'a><system.func><ifoo,'a>>.

Regards,

forki</ifoo,'a></system.func>

By on 2/24/2009 10:58 AM ()

Hi,
you should be able to cast the Expression to the generic type:

1
2
let quot = <@ fun (foo:IFoo) -> foo.Exceute("ping") @> // The body of the code MUST be inside <@ .. @>
let expr = (quot.ToLinqExpression() :?> Expression<Func<the_right_types_here>>)

EDIT: Here are some useful links regarding quotations:

Unfortunatelly, some of the names has changed since I wrote these articles, but it should explain the idea.

By on 2/24/2009 11:52 AM ()

Ok, thanks a lot.

I get the following code working:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
type Moq.Mock<'a> with        
 

  /// setup mock object


  member public x.expect (quot: Expr<func><Func<'a,'b>>) (returns:'b) =
     

    // create LINQ-Expression of quotation


    let expr = quot.ToLinqExpression() :?> Expression<func><Func<'a,'b>>


    x.Expect(expr).Returns(returns)


mock.expect (<@ Func<_,_>(fun y -> y.Execute("ping")) @>) 1000

But the call looks very complicated.

I am trying to hide the quotation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
type Moq.Mock<'a> with         


  /// setup mock object


  member public x.expect (f: 'a -> 'b) (returns:'b) =


    let quot: Expr<func><Func<'a,'b>> = <@ Func<'a,'b>(f) @> // I think here is the problem

     

    // create LINQ-Expression of quotation


    let expr = quot.ToLinqExpression() :?> Expression<func><Func<'a,'b>>


    x.Expect(expr).Returns(returns)


 mock.expect (fun y -> y.Execute("ping")) 1000

The second code fails with "System.NotSupportedException : Expression delegateArg is not supported". I think this is what you mean with "The body of the code MUST be inside <@ .. @>".</func></func></func></func>

By on 2/25/2009 2:17 AM ()

Hi,
I'm sure some of the articles that I referenced better explain the reason why it won't work if you don't place the function inside <@ .. @>, but briefly - if you enclose the code inside <@ .. @> it is compiled into quotations / data, but if you don't it is compiled into assembly code. You can't convert assembly code to quotations at runtime, so if you want qutoation / expression tree of some code, you have to enclose it into <@ .. @> or use ReflectedDefintion attribute (see the articles for details).

Regarding your question how to make it nicer - you cannot omit <@ .. @>, but you can encapsulate the wrapping of the F# lambda into Func delegate using "splicing operator" (I wrote a bit about splicing in one of the articles too). The syntax now uses "%<expr>" which means that the expression given as an argument is embedded into the quotation (as a quotation) and thus it can be converted to C# expression trees.

The Qutoations to LINQ translator doesn't support that automatically, so you need a small utility that looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
open System
open System.Linq.Expressions
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation

let (|CastToExpr|_|) (o:obj) = 
  match o with
  | :? Expr as e -> Some(e)
  | _ -> None
  
let rec expandSplice e = 
  match e with
  | Patterns.Call(target, mi, [Patterns.Value(CastToExpr(arg), ty)]) when mi.Name = "op_Splice" ->
      expandSplice arg
  | ExprShape.ShapeCombination(o, exprs) ->
      ExprShape.RebuildShapeCombination(o, List.map expandSplice exprs)
  | ExprShape.ShapeLambda(v, e) ->
      Expr.Lambda(v, expandSplice e)
  | ExprShape.ShapeVar(v) -> e

This can be used like this (here is some simple example, but you should be able to adapt it to your case):

1
2
3
4
5
6
7
8
let foo (f) =
  let quot = <@ new Func<_, _>(%f) @>
  let quot = expandSplice quot
  let e = (q.ToLinqExpression() :?> Expression<Func<int, int>>) // specify the right types here
  // do whatever you need with the 'e' expression here
  e.Compile().Invoke(10)

foo(<@ fun a -> a + a @>)
By on 2/25/2009 4:12 AM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper