你会如何测试它?多少次测试
本文关键字:测试 多少次 何测试 | 更新日期: 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