Mocking a method within a method with FakeItEasy

c#, fakeiteasy, unit-testing

Solution

First, let me say that I think there are fantastic points in Tseng's answer, especially about how

- Faking an interface means the "inner methods" can never be called, and

- You should be faking dependencies, not internals. If you have the option to make this change, do it, and stop reading my answer right now.

If you're still reading, I'm confused about two things:

- should `Test1` return `businessLogic`? As it's written (once the compilation errors are fixed), I would expect `Test1` to return 5 (not 15) when `Test2` returns 5.

- In `TestToTest`, when you set the `Returns(5)` on `Test2`, and then call `Test1`, since you faked an interface, I would expect sum to be 0, the default value for an int. I'm not sure how you'd get 5. In fact, I've replicated this behaviour in this test:

[TestMethod]
public void TestToTestInterface()
{
    //Arrange

    var instance = A.Fake<IClassWithMethods>();

    //Make calling Test2 return 5 and not 10.
    A.CallTo(() => instance.Test2()).Returns(5);

    //Call the method 
    var sum = instance.Test1();

    //Assert if the business logic in the method works.
    Assert.AreEqual(0, sum); // because Test1 wasn't faked
}

While I don't care for the approach myself, if you really want to have your replaceable code in `ClassWithMethods`, and then to test the `Test1` method, there's a way:

- We need to make `Test1` and `Test2` `virtual`, or they won't be fakeable.

- Fake out `ClassWithMethods`, not `IClasssWithMethods`.

- Tell the fake that when `Test1` is invoked, it should call the original code (which will in turn call the fake `Test2`).

I've put these changes all together, and this test passes for me:

public class ClassWithMethods : IClassWithMethods
{
    public virtual int Test1()
    {
        var value = this.Test2(); //Unittest should substitute with 5
        var businesslogic = value + 10; //The business logic

        return businesslogic;
    }

    public virtual int Test2()
    {
        return 10; //I try to mock this value away in the test. Don´t go here!
    }
}

[TestMethod]
public void TestToTestClass()
{
    //Arrange

    var instance = A.Fake<ClassWithMethods>();

    //Make calling Test2 return 5 and not 10.
    A.CallTo(() => instance.Test2()).Returns(5);

    // Make sure that Test1 on our fake calls the original ClassWithMethods.Test1
    A.CallTo(() => instance.Test1()).CallsBaseMethod();

    //Call the method 
    var sum = instance.Test1();

    //Assert if the business logic in the method works.
    Assert.AreEqual(15, sum);
}

Problem

How can I mock/facke the result from a function that is called in another function? Usually Test2 would be a DataAccess method that I dont like to fetch real data. What I like my unittest to test is the business logic. This Is what I have now but its not working at all. Sum is always asserted as 5! ``` public int Test1() { var value = this.Test2(); //Unittest should substitute with 5 var businesslogic = value + 10; //The business logic return businesslogic; } public int Test2() { return 10; //I try to mock this value away in the test. Don´t go here! } ``` Then I have a Unittest that I would like to run on my "business logic". ``` [TestMethod()] public void TestToTest() { //Arrange var instance = A.Fake<IClassWithMethods>(); //Make calling Test2 return 5 and not 10. A.CallTo(() => instance.Test2()).Returns(5); //Call the method var sum = instance.Test1(); //Assert if the business logic in the method works. Assert.AreEqual(15, sum); } ```

Original source