【问题标题】:Mocking with NSubstitute, needing some clarity.用 NSubstitute 模拟,需要一些清晰度。
【发布时间】:2016-09-08 10:53:07
【问题描述】:
我对如何正确模拟对象有点困惑。从我在 NSubstitute 的示例中看到的内容来看,这是断言的基本设置。我的理解是这是关于测试方法的行为。我的问题如下:
-
这是模拟获取设备主机名的正确方法吗?
[TestMethod]
public void MockedDeviceHostName()
{
//Arrange
var device = Substitute.For<IDeviceLogic>();
Device mockedDevice = new Device();
//Act
device.GetHostName("IP Address","Object Identifier Repository","CommunityString").Returns(mockedDevice.hostName);
//Assert
Assert.AreEqual(mockedDevice.hostName, device.GetHostName("IP Address", "Object Identifier Repository", "CommunityString"));
}
模拟有什么好处。我当然理解这是基于行为的测试,我的意思是我正在设置行为期望,所以我觉得即使方法出现错误,它们也总是正确的,在这种情况下。我正在寻找关于模拟与单元测试和集成测试的一些清晰说明。
【问题讨论】:
标签:
c#
visual-studio
unit-testing
mocking
nsubstitute
【解决方案1】:
Mocking 通常用于替换类/对象的依赖项,以便可以独立于该依赖项来测试其逻辑。
在您的示例中,实际上并没有依赖于模拟的IDeviceLogic 的类。更接近的例子可能是需要显示设备信息的表单。在这种情况下,最好在不连接真实设备的情况下运行表单逻辑的基本测试。
[Test]
public void SetDeviceNameOnLoad() {
//Arrange
var device = Substitute.For<IDeviceLogic>();
var view = Substitute.For<IDeviceView>();
var form = new DevicePresenter(device, deviceView);
device.GetHostName("IP Address","Object Identifier Repository","CommunityString").Returns("sample device name");
//Act
form.Load();
//Assert
Assert.AreEqual("sample device name", view.DeviceName);
}
这样做的一个好处是我们可以将我们想要测试的一些逻辑与瞬态条件(例如设备可能断开连接、网络可能关闭等)隔离开来。我们还可以模拟难以可靠自动化测试的条件(例如,我们模拟返回特定 HTTP 状态代码的 Web 服务)。而且我们可以加快测试速度(例如,一个设备可能需要 30 秒才能连接——我们可以模拟它来模拟它立即连接)。
缺点是我们只是在模拟依赖关系——如果真实的东西表现不同,我们的测试比无用更糟糕。例如,如果您必须在主机名可用之前在真实设备上调用device.Connect(),那么如果没有额外的工作,您的模拟将不会共享此行为。
希望这会有所帮助。