3

I have a database manipulating object as a dependency of my UUT (Unit Under Test). Therefore, I want to make it as a strict mock, because I also want to make sure that the UUT does not call any other methods that can result db change.

In rhino mocks I did the following:

  1. I made a strictmock from the db object
  2. I made an .Expect clause in Arrange
  3. I called VerifyAllExpectations in Assert

However, when I want to do this in FakeItEasy, I can't find how to do it without code duplication. I tried putting the CallsTo()+MustHaveHappened() parts in the Arrange, but then my test fail. If I put the CallsTo()+MustHaveHappened() parts in the Assert, then my test fail also, because unexpected calls were made to a strict fake. Can this be done without putting the CallsTo call into both Arrange and Assert?

Kornél Regius
  • 2,989
  • 5
  • 30
  • 39

2 Answers2

6

Whilst the answer from @jimmy_keen will work (I even upvoted it) a more idiomatic use of FakeItEasy would be:

// Arrange
var service = A.Fake<IService>(o => o.Strict()); // only allows configured calls
A.CallTo(() => service.PostData("data")).DoesNothing(); // allow a specific call

// Act
testedObject.CallService("data");

// Assert
A.CallTo(() => service.PostData("data")).MustHaveHappened(Repeated.Exactly.Once);

--- UPDATE ---

With help from @blairconrad over at https://github.com/FakeItEasy/FakeItEasy/issues/198#issuecomment-29145440 I think this is the neatest way to do this, without duplication:

// Arrange
var service = A.Fake<IService>(o => o.Strict()); // only allows configured calls
var expectedCall = A.CallTo(() => service.PostData("data"));
expectedCall.DoesNothing(); // allow the call

// Act
testedObject.CallService("data");

// Assert
expectedCall.MustHaveHappened(Repeated.Exactly.Once);
Adam Ralph
  • 29,453
  • 4
  • 60
  • 67
  • "Can this be done without putting the CallsTo call into both Arrange and Assert?" I knew this version and my question was exactly about avoiding this. – Kornél Regius Nov 23 '13 at 06:57
  • You have a point about the code duplication. Currently there's no way to achieve this with a strict fake without code duplication. I've re-opened the issue at FakeItEasy to discuss further https://github.com/FakeItEasy/FakeItEasy/issues/198#issuecomment-29138957 – Adam Ralph Nov 23 '13 at 19:02
  • Wow, so the CallTo returns a "call object" that can be verified later on. Interesting, upvoted. – Kornél Regius Dec 04 '13 at 14:58
  • 1
    Yeah, it's FakeItEasy. It's easy. ;-) – Adam Ralph Dec 05 '13 at 16:46
5

You can achieve that with following verifications:

var service = A.Fake<IService>();

testedObject.CallService("data");

// verify your specific call to .PostData
A.CallTo(() => service.PostData("data")).MustHaveHappened(Repeated.Exactly.Once);
// verify that no more than 1 call was made to fake object
A.CallTo(service).MustHaveHappened(Repeated.Exactly.Once); 

The A.CallTo(object) overload allows you to make a generic setup/verification on all and any of the fake object methods.

k.m
  • 30,794
  • 10
  • 62
  • 86
  • +1 this works. FYI I've polled the FIE owners to find out if there is a more elegant way to solve this https://github.com/FakeItEasy/FakeItEasy/issues/198 – Adam Ralph Nov 21 '13 at 06:42
  • And I answered @AdamRalph with a "why not just suck the `() => service.PostData…)` into a variable and use it in the Arrange and Assert? It's still two calls, as in this answer, but (I think) slightly more idiomatic FIE. – Blair Conrad Nov 25 '13 at 15:53