具有 Moq 单元测试的 Net Framework Xunit 保持调用原始功能

Net Framework Xunit With Moq Unit Testing Keep Calling The Original Function

我在模拟时遇到问题,因为它一直调用原始函数。这是我的演示代码

第一个文件是包含我要模拟的函数的接口。

public interface IDemoReplace
{
    int FunctionToBeReplaced();
}

第二个文件是一个 class,它实际上具有函数

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

第三个文件是我要测试的class

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

最后一个文件是测试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;
    }
}

此测试将失败,预期为 2,实际为 1。当我尝试调试时,它不会调用 returnTwo,而是调用原始函数。

我是单元测试的新手,所以我错过了什么?请注意,上面的代码只是我实际项目中发生的事情的演示。 FunctionToBeReplaced 实际上是一个从数据库执行和 return 记录的函数,所以我想模拟该函数。

谢谢:)

这是一个设计问题。被测主题与实现问题紧密耦合,这使得很难隔离主题以便对其进行单元测试。

它(主题)正在手动创建它的依赖关系

IDemoReplace replace = new DemoReplace();

理想情况下,您希望显式注入依赖项。这些依赖关系也应该是抽象的,而不是具体的。

public class ClassToBeTested {
    private readonly IDemoReplace dependency;

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

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

在 运行 时,可以完全或通过容器注入实现(或模拟)。

显示的原始示例中的测试现在应该按预期运行。

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;
    }
}