集成测试是否应该重做使用模拟的单元测试?
Should integration tests redo unit tests that use mocking?
在编写单元测试时,我一次只检查一个 class。如果我需要使用额外的 classes,那么我将使用模拟来确保测试是独立的。
稍后我想写集成测试,我是否应该copy/paste所有使用模拟的单元测试并在删除模拟对象后测试它们?
示例代码:
public class Event
{
string title;
List<Hour> hoursList = new List<Hour>();
public Event(string title) { this.title = title; }
public void AddHour(Hour newHour) { hoursList.Add(newHour); }
public int HourCount() { return hoursList.Count; }
public int TotalDuration() {
int total = 0;
foreach (var hour in hoursList)
total += hour.GetDuration();
return total;
}
}
public class Hour
{
string start;
string end;
public Hour(string start, string end) { this.start = start; this.end = end; }
public virtual int GetDuration() { /* algorightm calculating duration in minutes */ }
}
示例测试:
int expected = 165;
Event Concert = new Event("Local band concert");
Mock<Hour> ehMock = new Mock<Hour>("07:00", "08:30");
ehMock.Setup(x => x.GetDuration()).Returns(90);
Mock<Hour> ehMock2 = new Mock<Hour>("19:15", "20:30");
ehMock2.Setup(x => x.GetDuration()).Returns(75);
Concert.AddHour(ehMock.Object);
Concert.AddHour(ehMock2.Object);
Assert.AreEqual(expected, Concert.TotalDuration());
在上面的单元测试中,我正在测试来自事件 class 的 TotalDuration 方法,Hour class 被模拟并且我覆盖了 GetDuration() 方法。现在我应该使用相同的测试进行集成测试,但不使用 Mock 吗?
也许上面的例子太简单了,不需要集成测试。如果我有更高级的单元测试,那么推荐相同功能的集成测试?
在这种情况下,由于您没有在 ehMock
中设置任何内容,因此您从模拟中一无所获,因此在没有模拟的情况下进行集成测试只会做同样的事情。此外,向构造函数添加参数(例如“07:00”)意味着您实际上是在反对模拟,因为这一直都是一个确切的例子。 Tldr;我将此示例称为集成测试。
一个更抽象的答案:这两件事的范围完全不同。
存在单元测试以测试您的各个单元的所有 方面。所有单位,其所有功能。待隔离检测。换句话说:你建造了一大堆乐高积木,你的单元测试告诉你所有这些积木完全按照它们应该做的去做。
另一方面:集成测试归结为确保正确的集成。意思是:你想出你最重要的 "paths",你想被录取,然后你写 integration/function 测试来敲定这些。
testing pyramid 的重点是保留单元测试,这样您就可以编写更少数量的集成测试。因为单元测试 运行 很快,可以帮助您快速识别和修复错误。集成测试更重要,但也
更昂贵*,而且您仅将它们用于无法正确进行单元测试的事情。
因此:集成测试当然会 "test" 您的单元测试已经验证的事情。但是您 不 只想将所有单元测试转换为集成测试。
在编写单元测试时,我一次只检查一个 class。如果我需要使用额外的 classes,那么我将使用模拟来确保测试是独立的。
稍后我想写集成测试,我是否应该copy/paste所有使用模拟的单元测试并在删除模拟对象后测试它们?
示例代码:
public class Event
{
string title;
List<Hour> hoursList = new List<Hour>();
public Event(string title) { this.title = title; }
public void AddHour(Hour newHour) { hoursList.Add(newHour); }
public int HourCount() { return hoursList.Count; }
public int TotalDuration() {
int total = 0;
foreach (var hour in hoursList)
total += hour.GetDuration();
return total;
}
}
public class Hour
{
string start;
string end;
public Hour(string start, string end) { this.start = start; this.end = end; }
public virtual int GetDuration() { /* algorightm calculating duration in minutes */ }
}
示例测试:
int expected = 165;
Event Concert = new Event("Local band concert");
Mock<Hour> ehMock = new Mock<Hour>("07:00", "08:30");
ehMock.Setup(x => x.GetDuration()).Returns(90);
Mock<Hour> ehMock2 = new Mock<Hour>("19:15", "20:30");
ehMock2.Setup(x => x.GetDuration()).Returns(75);
Concert.AddHour(ehMock.Object);
Concert.AddHour(ehMock2.Object);
Assert.AreEqual(expected, Concert.TotalDuration());
在上面的单元测试中,我正在测试来自事件 class 的 TotalDuration 方法,Hour class 被模拟并且我覆盖了 GetDuration() 方法。现在我应该使用相同的测试进行集成测试,但不使用 Mock 吗?
也许上面的例子太简单了,不需要集成测试。如果我有更高级的单元测试,那么推荐相同功能的集成测试?
在这种情况下,由于您没有在 ehMock
中设置任何内容,因此您从模拟中一无所获,因此在没有模拟的情况下进行集成测试只会做同样的事情。此外,向构造函数添加参数(例如“07:00”)意味着您实际上是在反对模拟,因为这一直都是一个确切的例子。 Tldr;我将此示例称为集成测试。
一个更抽象的答案:这两件事的范围完全不同。
存在单元测试以测试您的各个单元的所有 方面。所有单位,其所有功能。待隔离检测。换句话说:你建造了一大堆乐高积木,你的单元测试告诉你所有这些积木完全按照它们应该做的去做。
另一方面:集成测试归结为确保正确的集成。意思是:你想出你最重要的 "paths",你想被录取,然后你写 integration/function 测试来敲定这些。
testing pyramid 的重点是保留单元测试,这样您就可以编写更少数量的集成测试。因为单元测试 运行 很快,可以帮助您快速识别和修复错误。集成测试更重要,但也 更昂贵*,而且您仅将它们用于无法正确进行单元测试的事情。
因此:集成测试当然会 "test" 您的单元测试已经验证的事情。但是您 不 只想将所有单元测试转换为集成测试。