Mocking a method which inside another method using FakeItEasy

1.3k views Asked by At

I wish to mock a "B" method that is called inside the method "A"

Here is an example In the below example I want MapPath to always return some "text" whenever it's being called.

Both are in different classes

public  class TestTest
{            
    public virtual string Test1()
    {
        ServerPath IFilePath = new ServerPath();
        string path = IFilePath.MapPath("folder", "filepath");
        return path;
    }
}

public class ServerPath
{
    public virtual string MapPath(string folder, string filepath)
    {
        Console.WriteLine("ServerPath");
        return (System.Web.Hosting.HostingEnvironment.MapPath(folder + filepath));
    }
}

I want to mock in such a way that when there is call to MapPath it should always returns "test25" (Whether I should implement an interface?)

My TestCode:

//I am using FakeitEasy
TestTest TestClass = new TestTest();
var FakeServerPath = A.Fake<ServerPath>();
var FakeTestTest = A.Fake<TestTest>();

A.CallTo(() => FakeServerPath.MapPath(A<string>.Ignored, A<string>.Ignored)).Returns("test25");

//Should I call FakeTestTest.Test1() or TestClass.Test1() ?
Console.WriteLine(TestClass.Test1());
1

There are 1 answers

2
Nkosi On BEST ANSWER

You are manually newing up an instance of ServerPath which tightly couples TestTest to it. This makes mocking it a little more difficult. It should be injected into TestTest as a dependency

I would advise abstracting the dependency

public interface IFilePath {
    string MapPath(string folder, string filepath);
}

public class ServerPath : IFilePath {
    public virtual string MapPath(string folder, string filepath) {
        Console.WriteLine("ServerPath");
        return (System.Web.Hosting.HostingEnvironment.MapPath(folder + filepath));
    }
}

and making it an explicit dependency of TestTest

public  class TestTest {
    private readonly IFilePath filePath;

    public TestTest (IFilePath filePath) {
        this.filePath = filePath;
    }

    public virtual string Test1() {
        string path = filePath.MapPath("folder", "filepath");
        return path;
    }
}

So that now you can mock it for testing

//Arrange
var expected = "test25";
var FakeServerPath = A.Fake<IFilePath>();    
A.CallTo(() => FakeServerPath.MapPath(A<string>.Ignored, A<string>.Ignored))
 .Returns(expected);

var sut = new TestTest(FakeServerPath);

//Act
var actual = sut.Test1();

//Assert
Assert.AreEqual(expected, actual);

Finally you would make sure to register the abstraction and implementation with the DI container in the composition root.