FakeItEasy: Reset Fake Calls History / Ignore Call
Asked Answered
A

2

7

I would like to reset a Fake Calls History or ignore a Call.

The fake asserted method is called in the Init method in the tested class constructor and I want to ignore this call because it's not part of the tested action.

Here an example:

[TestClass]
public class UnitTest1
{
    private MyFakedClass myFakedObject;
    private SUT sut;

    [TestInitialize]
    public void Init()
    {
        myFakedObject = A.Fake<MyFakedClass>();
        sut = new SUT(myFakedObject); //constructor calls myFakedObject.AssertedMethod()
    }

    [TestMethod]
    public void TestMethod1()
    {
        sut.TestedMethod(); //TestedMethod calls myFakedObject.AssertedMethod() again...
        A.CallTo(() => myFakedObject.AssertedMethod()).MustHaveHappened(Repeated.Exactly.Once); 
//...So this is false
    }
}
Arletha answered 17/3, 2015 at 9:5 Comment(0)
I
14

I love @forsvarir's answer. I would be inclined to think that the call from within the constructor is significant.

However, if you really need to do this:

When FakeItEasy version ≥ 3.2.0, you can use ClearRecordedCalls:

Fake.ClearRecordedCalls(fake);

When 2.0.0 ≤ FakeItEasy version < 3.2.0, consider the forsvarir's subtraction method (FakeItEasy: Reset Fake Calls History / Ignore Call).

When FakeItEasy version < 2.0.0, you can use scopes:

[Test]
public void TestMethod1()
{
    using (Fake.CreateScope())
    {
        sut.TestedMethod(); // calls myFakedObject.AssertedMethod() again
        A.CallTo(() => myFakedObject.AssertedMethod())
         .MustHaveHappened(Repeated.Exactly.Once);
    }
}

Using the scope causes MustHaveHappened to look only at calls made from within the scope.

You could also create the scope in the TestInitialize and dispose of it in the TestCleanup method, if you wanted to keep the using outside of all your test methods.

Index answered 17/3, 2015 at 11:3 Comment(1)
I was impressed that someone knew how to do this, then I saw that it was you @Blair Conrad! Still a little impressed though.Hissing
M
4

This feels wrong to me. Typically I would expect the cost of object creation to be part of the expectations of the tests for that object. Obviously, it depends upon what your AssertedMethod does, however, would your test really still be valid if your constructor didn’t call it? Would your SUT be in the expected state that your class needs?

I can’t see anything in the fakeiteasy framework to allow you to reset the count, although as I’ve said, this doesn’t feel like the right thing to do so I wasn’t really expecting to find it. It seems like a simple way to achieve what you seem to be trying to do, whilst still acknowledging at least at a TestClass level that you know there is a call in the constructor/init would be something like this:

const int InitAssertedMethodCalls = 1;

[TestMethod]
public void TestMethod1()
{
    sut.TestedMethod(); 
    A.CallTo(() => myFakedObject.AssertedMethod())
             .MustHaveHappened(Repeated.Exactly.Times(1 + InitAssertedMethodCalls )); 
}
Melinamelinda answered 17/3, 2015 at 10:29 Comment(1)
Thanks @forsvarir. In my case the test is effectively still valid even if the constructor didn't call the assertedMethod but I agree with your point of view.Arletha

© 2022 - 2024 — McMap. All rights reserved.