Scope level rules #27

Closed
wants to merge 2 commits into
from

Conversation

Projects
None yet
5 participants

Hi,

I have added suport for scope level user rules. With this mechanism You can add a rule to scope and all calles in scope will use this rule.

I've also upgraded the sln to vs 2012 it should now work on 2012 and 2010. You can pick only my secound commit to revert VS upgrade.

Hope You like my idea with scope level rules.

regards,

Sławek

Owner

adamralph commented Jan 31, 2013

Thanks very much for contributing.

Has this new feature been discussed anywhere? Are there any examples showing how it can be used and what benefits it provides?

Member

patrik-hagne commented Feb 7, 2013

I think this provides a way to apply a rule to all fakes that are used within that scope. So, for example, if I create a scope I can then say something like: "any call to a ToString-method on any fake within this scope should return 'hello world'". Do I get that right?

I think this is a great feature and the implementation is a good technical implementation. I do believe we need a good api for it before doing it though.

Owner

adamralph commented Feb 7, 2013

Shall we raise an issue for it, so we can discuss it and agree a design, independent of any pull requests?

Member

patrik-hagne commented Feb 7, 2013

Sure if anybody is interested in it, why not?

Owner

adamralph commented Feb 7, 2013

@skwasiborski if you're still interested in driving this, could you please raise an issue so we can discuss the feature and agree an API.

It would be good if you could provide some detail about your proposed design including examples of how it might be used.

Member

patrik-hagne commented Mar 4, 2013

If we should create such a feature I believe that it should be the following syntax:

using (Fake.CreateScope())
{
    A.Call.Throws(new Exception());
    A.Call.WithReturnType<string>().Returns("foo");
}

This would affect all any fake object for the lifetime of that scope. Trying to configure like this when no scope is created an exception should be thrown.

Owner

adamralph commented Mar 4, 2013

I like that. I presume that the first set up acts for any call to any fake and the second one supersedes it only for methods with a string return type?

Would we also need this?

A.Call.WIthVoidReturnType.Throws(new Exception());

Just throwing out some alternatives for consideration:

Any.Call.Throws(new Exception());
Any.Call.WithReturnType<string>().Returns("foo");

A.Fake.Throws(new Exception());
A.Fake.WithReturnType<string>().Returns("foo");

All.Fakes.Throw(new Exception());
All.Fakes.WithReturnType<string>().Return("foo");

A.CallTo(() => A.Fake).Throws(new Exception());
A.CallTo(() => A.Fake.WithReturnType<string>()).Returns("foo");
Member

patrik-hagne commented Mar 4, 2013

You're correct, that's the way I think it should work. That's the way it works in the two CallTo-overloads.

I like your alternatives, actually there used to be an "Any" class (maybe it's still there for backwards compatibility, I don't remember. However, one of the things I've strived for in the API is that the A-class should be the entry point for any configuration, I believe that leads to better discoverability of the API. It wasn't like that from the beginning but several things has been moved to the A-class and every time it's "clicked" for me.

The A.Call-property should just return the exact same type as the A.CallTo(object)-overload does.

Contributor

danielmarbach commented Mar 6, 2013

I think it is a good design decision to have or go for a single entry point. But sometimes it is good to hide away the lesser used features because otherwise if an api entry point has too many methods it gets confusing too.

That's why I like Any or All. Another alternative could be the ravendb approach:

A.Advanced.CallTo or Adams suggestions

Or for cool sentence like structure

A.Ny.CallTo

Bit weird but funky :)

Owner

adamralph commented Mar 6, 2013

After reading @patrik-hagne's last comment I'm in agreement that A should be the entry point for the benefit of discoverability and I'm currently favouring his original suggestion. But I also agree that we shouldn't overload any given entry point with too much. I'll have to look at A more closely before giving an opinion on that.

Member

patrik-hagne commented Mar 6, 2013

I'm not at all sure that the scope level rules would be a lesser used feature. I'm convinced of the opposite.

Owner

adamralph commented Mar 6, 2013

@hmemcpy With so many mocking frameworks available, why should one chose #FakeItEasy? https://twitter.com/krenaud/status/308678833215787009

@krenaud I love the API. Fluent, no polluting extension methods, and everything starts with A. Simple. https://twitter.com/hmemcpy/status/308679476173225984

😉

Contributor

hmemcpy commented Mar 6, 2013

Disclaimer: I used to work for at Typemock.

The Typemock Isolator API is very similar to FakeItEasy's (which made me fall in love with it), everything starts with a single entry point (Isolate...). One difference, though, is that the verification portion existed as their own set of methods, rather than being an extension method (like .MustHaveHappened). In Isolator there was:

Isolate.Fake.* - to create fake instances
Isolate.WhenCalled(() => ...) - like FIE's A.CallTo
Isolate.Verify.WasCalled()/WasNotCalled() for verification.

I haven't yet read this entire thread (just got an email because I was mentioned here), but I do prefer Isolator's way of doing verification - It's more visible. Sometimes even I have to hunt for that MustHaveHappened to distinguish the setup from verification. Other than that, I never had an issue with FIE's API discoverability (I do have to Google every time I need to raise an event with FIE though :)).

My 2c.

Owner

adamralph commented Mar 6, 2013

Design discussion moved to #78

@ghost ghost assigned patrik-hagne Apr 22, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment