AutoFixture and fluent Moq syntax
Asked Answered
B

2

5

I've been using Moq for a while, and for brevity I more often than not express setups using the fluent syntax of Mock.Of...

var foo = Mock.Of<IFoo>(f => f.Method(It.IsAny<string>()) == 7 && f.Property == "Hi");
var sut = new Whatever(foo);

Recently, I've started playing around with AutoFixture and can't seem to find any equivalent syntax for expressing multiple setups at once. I understand that I can express the same thing using Freeze...

var foo = fixture.Freeze<Mock<IFoo>>();
foo.Setup(f => f.Method(It.IsAny<string>()).Returns(7);
foo.Setup(f => f.Property).Returns("Hi");
var sut = fixture.Create<Whatever>();

...but if at all possible, I'd like to get the benefits of automocking, and keep the brevity of the fluent Moq setups. Stylistic arguments aside, does AutoFixture expose any way for me to express those setups fluently? If not, is there any optimization I can use to make the AutoFixture setups more terse?

Betroth answered 23/4, 2015 at 0:26 Comment(2)
Have you considered using NSubstitute? It's OOTB significantly cleaner than Moq (there's an AutoNSubstitute glue library too) so if you don't have a significant unignorable sunk cost you have nothing t lose but parentheses :)Lohner
@RubenBartelink, in this case specifically I'm working with 10k+ Moq/NUnit based tests in a corporate environment so a framework switch probably isn't likely. For my personal projects however I'll definately have a look at it (the few comparisons I could find online were quite contrived and compared NSubstitute against the non-fluent Moq syntax which is pretty 'wordy', so I'll have to do a bit of research and try it out myself).Betroth
H
5

You could create the mock yourself using Moq's fluent API, and then inject it back into the fixture:

var foo = Mock.Of<IFoo>(f => f.Method(It.IsAny<string>()) == 7 && f.Property == "Hi");
fixture.Inject(foo);

var sut = fixture.Create<Whatever>();

If you're using the AutoMoqCustomization, then the code above will do the same thing as the code you posted, apart from not setting CallBase = true and DefaultValue = DefaultValue.Mock;.

If you're using AutoConfiguredMoqCustomization, then this code will not setup any additional members, whereas the customization would. If you want to reap the benefits of AutoConfiguredMoqCustomization and use Moq's fluent API, I'm afraid that's not possible.

Hoogh answered 23/4, 2015 at 8:31 Comment(3)
Nice. If you include the helper and/or merge in my answer, I'll delete mine as the key thing to get across is the fact that the autoconfig is knocked out with an Inject as you say.Lohner
@RubenBartelink I don't want to steal credits from you, let's keep both answers ;)Hoogh
@dcastro, thanks - that answers my question. I was hoping it was baked directly into Freeze or one of the other methods somehow so I could cut down on the noise that an additional Mock.Of<T> introduces. I'd already used helper methods (both extension and instance) to clean it up so your answer and the helper methods from Ruben will suffice. I'm using AutoMoqCustomization so Inject usage shouldn't be a problem. Thanks again.Betroth
L
5

Riffing on @dcastro's answer, a small wrapper which would have the same caveats as covered there:-

public static T SetMock<T>(this IFixture that, Expression<Func<T, bool>> expr)
    where T : class
{
    var mocked = Mock.Of(expr);
    that.Inject(mocked);
    return mocked;
}

Allows you to:

fixture.SetMock<IFoo>(f => 
    f.Method(It.IsAny<string>()) == 7 
    && f.Property == "Hi");

Or, iff you're interested in the concrete value:

var foo = fixture.SetMock<IFoo>(f => 
    f.Method(It.IsAny<string>()) == 7 
    && f.Property == "Hi");

The cleanest C# with no helpers is:

fixture.Inject( Mock.Of<IFoo>( f => 
    f.Method(It.IsAny<string>()) == 7 
    && f.Property == "Hi")));

And if you're doing your tests in F#, with Foq, you would write that as:

Mock<IFoo>.With(fun x ->
    <@  x.Method(any()) --> 7
        x.Property --> "Hi" @>)
|> fixture.Inject

(the expression to the right of the --> is just code, i.e. you can put algorithmic stuff in there and you get intellisense and type checking while you write it). Or (still with Foq):

fixture.Inject <|
    Mock<IFoo>.With(fun x -> <@  
        x.Method(any()) --> 7
        x.Property --> "Hi" @>)

Or (assuming the interface makes sense to implement completely) you can use F# object expressions:

fixture.Inject { new IFoo with 
    member x.Method _ = 7 
    member x.Property with get() = "Hi" }
Lohner answered 23/4, 2015 at 9:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.