如何在 C# 中模拟 return 虚拟数据的方法?

How to mock methods to return dummy data from them in C#?

我有一个 class,我正试图通过用 C# 编写一些单元测试来测试它。我还在单元测试中使用 Moq 库进行模拟。

下面是我的 class 中的一些方法,我想模​​拟这些方法,以便它们可以 return 一些我想要 return 的虚拟数据。

public class DataManager
{

    public DataManager(ILoggingService loggingService, IConfiguration configuration)
    {
        // ...
    }

    // how to mock this to return dummy data?
    private DataHolder GetData()
    {
        //... return DataHolder object
    }

    // how to mock this to return dummy data?
    private IEnumerable<ProcessClient> GetClientValues(string value)
    {
        //... return IEnumerable<ProcessClient> object
    }

}

这就是我测试它的方式:

    private Mock<ClientUtility> utility;

    [SetUp]
    public void Setup()
    {
        utility = new Mock<ClientUtility>();
    }

    [Test]
    public void Test1()
    {

        // what should I do here so that "GetData" and "GetClientValues" return dummy data when I call below class constructor?
        
        var testName = "config1";
        var testContent = "{}";

        utility.Setup(x => x.Add(new DataStatus { Pin = "test" }, "data.com", "test")).Returns(Task.FromResult(true));
        var dataManager = new DataManager(loggingService.Object, configuration.Object);

        Assert.AreEqual(testContent, dataManager.GetStuff(testName)[0]);
    }

问题:

我如何使用 Moq 或任何其他库模拟“GetData”和“GetClientValues”以从这两种方法 return 虚拟数据?这可能吗?

我认为你可以使用 CallBase = true。 所以你的模拟将表现得像 true class.

var dataManager = new Mock<DataManager>(loggingService.Object, configuration.Object) { CallBase = true };

dataManager.Object.Method1();
dataManager.Object.Method2();

并且您可以像使用实用程序一样模拟一些方法。

在页面上按“CallBase”搜索:

https://github.com/Moq/moq4/wiki/Quickstart

更新 我制作了方法 public 来调用它们。 还有一些问题,我上次没有看到。如果你想改变它们的行为,你需要制作“虚拟”方法。

有代码示例。如您所见,GetClientValues() returns 真实数据,因为我们使用 CallBase = trueGetData() returns 虚拟数据调用默认真实实现,因为我们模拟了它的行为。

public class DataManager
    {

        public DataManager(ILoggingService loggingService, IConfiguration configuration)
        {
            // ...
        }

        // how to mock this to return dummy data?
        public virtual DataHolder GetData()
        {
            return new DataHolder
            {
                Data = "RealData"
            };
        }

        // how to mock this to return dummy data?
        public IEnumerable<ProcessClient> GetClientValues(string value)
        {
            return new List<ProcessClient>
            {
                new ProcessClient
                {
                    Data = "RealData"
                }

            };
        }

    }

和测试。

public class Tests
    {
        [SetUp]
        public void Setup()
        {
        }

        [Test]
        public void Test1()
        {
            var loggingService = new Mock<ILoggingService>();
            var config = new Mock<IConfiguration>();
            var dataManager = new Mock<DataManager>(loggingService.Object, config.Object){CallBase = true};
            dataManager.Setup(x => x.GetData()).Returns(new DataHolder { Data = "FakeData" });

            Assert.AreEqual("RealData", dataManager.Object.GetClientValues("test").First().Data);
            Assert.AreEqual("FakeData", dataManager.Object.GetData().Data);

        }
    }

但无论如何我认为,这种方法不适合测试。 测试私有方法有问题。我们有一些方法(例如Invoke()),但总的来说,“如果你想对私有方法进行单元测试,可能会出现问题”。我想推荐你阅读一些关于测试设计和编写可测试代码的内容。 关于测试私有方法 How do you unit test private methods?.