1

I have a problem with mocking cause it keep calling the original function. This is my demo code

First file is interface that contains the function that I want to mock.

public interface IDemoReplace
{
    int FunctionToBeReplaced();
}

Second file is a class that actually has the implementation for the function

public class DemoReplace : IDemoReplace
{
    public int FunctionToBeReplaced()
    {
        //this function contains sql query in my real project
        return 1;
    }
}

Third file is a class that I want to test

public class ClassToBeTested
{
    public int TestThisFunction()
    {
        IDemoReplace replace = new DemoReplace();
        var temp = replace.FunctionToBeReplaced();
        return temp;
    }
}

Last file is the test class

public class TestClass
{

    [Fact]
    public void TryTest()
    {
        using (var mock = AutoMock.GetLoose()) {
            //Arrange
            mock.Mock<IDemoReplace>()
                .Setup(x => x.FunctionToBeReplaced())
                .Returns(returnTwo());

            var classToBeTested = mock.Create<ClassToBeTested>();
            var expected = 2;

            //Act
            var actual = classToBeTested.TestThisFunction();

            //Assert
            Assert.Equal(expected, actual);
        }
    }

    public int returnTwo() {
        return 2;
    }
}

This test will be failed with expected is 2 and actual is 1. When I tried to debug it doesn't call returnTwo but call the original function instead.

I am new to unit testing so what did I miss? Please be considered that the code above is only a demo of what is happened in my actual project. FunctionToBeReplaced is actually a function that execute and return record from database so I want to mock that function.

Thanks :)

Irvan
  • 165
  • 1
  • 13
  • this is a design issue. The subject under test is tight coupled to implementation concerns that make it difficult to isolation the subject so that it can be unit tested – Nkosi Mar 23 '20 at 10:42

1 Answers1

1

This is a design issue. The subject under test is tight coupled to implementation concerns that make it difficult to isolation the subject so that it can be unit tested.

It (subject) is manually creating its dependency

IDemoReplace replace = new DemoReplace();

Ideally you want to explicitly inject dependencies. Those dependencies should also be abstractions and not concretions.

public class ClassToBeTested {
    private readonly IDemoReplace dependency;

    public ClassToBeTested(IDemoReplace dependency) {
        this.dependency = dependency;
    }

    public int TestThisFunction() {            ;
        var temp = dependency.FunctionToBeReplaced();
        return temp;
    }
}

At run time, the implementation (or mock) can be injected, either purely, or via a container.

The test in the original example shown should now behave as expected.

public class TestClass {
    [Fact]
    public void TryTest() {
        using (var mock = AutoMock.GetLoose()) {
            //Arrange
            var expected = returnTwo();
            mock.Mock<IDemoReplace>()
                .Setup(x => x.FunctionToBeReplaced())
                .Returns(expected);

            var classToBeTested = mock.Create<ClassToBeTested>();

            //Act
            var actual = classToBeTested.TestThisFunction();

            //Assert
            Assert.Equal(expected, actual);
        }
    }

    public int returnTwo() {
        return 2;
    }
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Thanks!! Now it is working like a charm. Hmm to be honest the real project is already deployed and running but all of the service is designed that way. So is there any other solution than refactoring it one by one? @Nkosi – Irvan Mar 24 '20 at 09:25