0

We're considering switching from Rhino to FakeItEasy for our mocking framework. The main reason is simplicity, in FakeItEasy there's only one way to do things. Rhino has record/playback, AAA, stub, partial mock, strict mock, dynamic mock, etc.

I'm rewriting some of our tests using FakeItEasy to ensure it will do everything Rhino is currently doing for us, and I've encountered something I can't explain and was hoping someone could enlighten me.

In Rhino, I have the following test. The code has been abbreviated.

ConfigurationManagerBase configManager = _mocks.Stub<ConfigurationManagerBase>();

using( _mocks.Record() )
{
    SetupResult
        .For( configManager.AppSettings["ServerVersion"] )
        .Return( "foo" );
}

The unit test to which this code is attached runs just fine and the test passes. I rewrote it using FakeItEasy as follows.

ConfigurationManagerBase configManager = A.Fake<ConfigurationManagerBase>();

A.CallTo( () => configManager.AppSettings["ServerVersion"] )
    .Returns( "foo" );

Now when I run the test it fails, but it's because FakeItEasy is throwing an exception.

The current proxy generator can not intercept the specified method for the following reason:
  - Non virtual methods can not be intercepted.

That seemed odd, because Rhino has the same restriction. What we think is happening in that while AppSettings is virtual on ConfigurationManagerBase, the indexer property is not. We corrected the problem by changing the FakeItEasy test to read.

NameValueCollection collection = new NameValueCollection();
collection.Add( "ServerVersion", "foo" );

A.CallTo( () => configManager.AppSettings )
    .Returns( collection );

I'm basically just trying to understand whether I'm doing something wrong with FakeItEasy or is Rhino performing some "magic" behind the scenes with that indexer?

Craig W.
  • 17,838
  • 6
  • 49
  • 82
  • We've had numerous problems where people created Stubs when they really wanted mocks, or created a Strict mock when a dynamic would have done, and the test either didn't work or gave incorrect results. We'd like to reduce the chances of those things happening. Having said that, the purpose of the post was to help me understand the different behavior, not to debate whether we should make the switch or not. – Craig W. Aug 26 '11 at 17:41
  • 1
    Not sure at all, I think that it works a bit "by coinsidence" in Rhino. There are a couple of alternatives as too why. Maybe the indexer is non virtual but it internally invokes some virtual method (like GetItem("ServerVersion")) or similar. FakeItEasy wouldn't have the same behaviour in that case since it parses the expression and uses the Indexer directly. To verify this you could try to use the record/replay model that is available in FakeItEasy too (but shouldn't be used in most cases). – Patrik Hägne Aug 30 '11 at 14:29

1 Answers1

0

The following configuration should be similar to what Rhino does if this doesn't work Rhino does something magic:

NextCall.To(configManager.AppSettings).Returns("foo"); 
var ignored = configManager.AppSettings["ServerVersion"];
Patrik Hägne
  • 16,751
  • 5
  • 52
  • 60