C# 中的最小起订量和文件/数据保存

MJR*_*MJR 5 c# unit-testing moq

好的,我正在做一些单元测试,我的理解是(基于 Roy Osherove 的“单元测试的艺术”),如果您正在访问数据库或实际保存文件,那么您是集成测试,而不是单元测试。

鉴于此,我有以下几点(是的,我知道这违反了 SRP,但它说明了我的观点):

public class PrimeChecker : IPrimeChecker
{
    public bool IsPrime(int num)
    {
        if (num < 2)
        {
            return false;
        }

        if (num > 2 && num % 2 == 0)
        {
            return false;
        }

        if (num % 2 != 0)
        {
            for (int i = 3; (i * i) <= num; i += 2)
            {
                if (num % i == 0)
                {
                    return false;
                }
            }
        }

        return true;
    }

    public bool Save()
    {
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

注意 Save() 方法现在只是一个存根。

我正在尝试使用 Moq 来模拟保存。所以我的测试看起来像这样:

[Test]
    public void Save_WhenCalled_ExecutesSave()
    {
        var mock = new Mock<IPrimeChecker>();

        mock.Setup(x => x.Save());

        IPrimeChecker checker = mock.Object;
        checker.Save();

        mock.Verify(x => x.Save(), Times.Once);
    }
Run Code Online (Sandbox Code Playgroud)

因此,如果我的类中有一个功能齐全的 Save() 方法,这是模拟功能的正确方法吗?因为正如我之前所说的,我的理解是对于单元测试,我不应该实际写入文件/保存到数据库。

如果这是不正确的,什么应该我做?

Nko*_*osi 5

假设您的检查器依赖于需要保存的内容。

可以说

public interface IPrimeDb {
    bool Save(int prime);
}
Run Code Online (Sandbox Code Playgroud)

检查器看起来像这样

public class PrimeChecker {
    private IPrimeDb primeDb;

    public PrimeChecker(IPrimeDb db) {
        this.primeDb = db;
    }

    public bool IsPrime(int num) {
        if (num < 2) {
            return false;
        }

        if (num > 2 && num % 2 == 0) {
            return false;
        }

        if (num % 2 != 0) {
            for (int i = 3; (i * i) <= num; i += 2) {
                if (num % i == 0) {
                    return false;
                }
            }
        }

        return true;
    }

    public bool Save(int prime) {
        if (IsPrime(prime))
            return primeDb.Save(prime);

        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

在提供有效素数时测试是否正在调用保存的测试可能如下所示。

[TestMethod]
public void Save_WhenCalled_ExecutesSave() {
    //Arrange
    var num = 3;
    var mock = new Mock<IPrimeDb>();

    var sut = new PrimeChecker(mock.Object);

    mock.Setup(_ => _.Save(num)).Returns(sut.IsPrime(num));

    //Act
    var actual = sut.Save(num);

    //Assert
    Assert.IsTrue(actual);
    mock.Verify(_ => _.Save(num), Times.AtMostOnce());
}
Run Code Online (Sandbox Code Playgroud)

在单元测试时,您倾向于模拟被测对象的依赖项,以避免出现不良行为。这允许单独进行测试。