你会如何测试它?多少次测试

本文关键字:测试 多少次 何测试 | 更新日期: 2023-09-27 18:10:01

我有这个类(这是更多的伪代码)


public class Roles
{
    private ProcessData processData;
    Roles(ProcessData pd)
    {
        processData = pd;
    }
    public string[] GetLoginsThatCanCallAction(string actionName)
    {
        return GetPeopleThatCanCallActionFromDb(actionName)
            .Union(processData.ProcessOwner)
            .Union(GetFromDb(Role.Administrators);
            // there may be many more Union(xyz) calls here
            .ToArray();
    }
    // I can refactor those methods to be mockable
    private GetPeopleThatCanCallActionFromDb(...)
    private GetFromDb(...)
}

我的问题是。你会在GetLoginsThaatCanRunAction方法中为每个Union调用编写一个测试吗?或者我只需要编写一个测试并断言方法返回从GetLoginsThatCanCallAction内部调用的所有方法返回的登录。

我可以看到两种方法都有道理。但也许有人会说服我采用另一种解决方案。

编辑:我想我没有说清楚我的问题:我想问你是否会写这个测试


var pd = new ProcessData()
pd.ProcessOwner = "Owner";
var r = new Roles(processData)
SetupSoThatCallsForPeopleThatCanCallActionWillReturn("Joe");
SetupSoThatCallForAdministratorsWillReturn("Administrator");
var logins = r.GetLoginsThatCanCallAction("some action");
Assert.That(logins, Contains("Owner");
Assert.That(logins, Contains("Joe");
Assert.That(logins, Contains("Administrator");

还是将它分成3个独立的测试,每个测试中有一个Assert ?

你会如何测试它?多少次测试

有趣的话题,你的问题是,你正试图写一个测试用例后,你有一些代码开发。我将对每个Union调用进行一次测试。原因是你想测试,你得到一个值从所有方法返回或你想测试,在不同的假设下,每个方法将返回登录?

对我来说,更重要的是知道每个方法将返回一个登录基于不同的用例,而不是一个通用的测试,将返回我通过/失败。

我将为GetLoginsThatCanCallAction编写一个模拟外部对象的测试。从您的示例中,这可能意味着嘲弄Union调用。原因是,当我写这段代码时,我不关心Union中使用的逻辑。(我有一些案例,我甚至还没有写)。

如果联合调用的行为可以改变(即抛出异常),我将对这些行为分别进行测试。然而,我会让我的测试套件为我生成那些测试用例,而不是试图手工编写它们。

您关心GetLoginsThatCanCallAction的行为是否正确。您还需要控制Union调用返回的内容。

也就是说,您还希望有一个执行GetLoginsThatCanCallAction使用的整个过程的自动化测试,以便您在单元测试中验证您正在模拟的类之间的连接。除非不可能自己手动执行进程。

另一个注意事项,如果类难以测试。这是一种代码味道,说明你的设计没有模块化。

我也会避免模拟类的内部方法,如果你需要这样做来测试函数。这表明你的类中隐藏着另一个类。你的类正在做不止一件事S在SOLID

您应该只使用被测单元的公共API。您的单元有一个公共方法GetLoginsThatCanCallAction。无论这个方法是否调用其他方法,还是作为一个大方法实现,都无关紧要。这是一个实现细节。真正重要的是这个方法是否正确地与依赖项通信并返回预期的结果:

// Arrange
Mock<IProcessData> processData = new Mock<IProcessData>();
processData.Setup(d => d.ProcessOwner).Returns(new[] { "Bob" });
var expected = new []{ "Bob", "Joe" };
// Act
var actual = roles.GetLoginsThatCanCallAction("Drink");
// Assert
processData.VerifyGet(d => d.ProcessOwner); // verify communication
CollectionAssert.AreEquivalent(expected, actual); // verify result