c# - 从抽象类继承并实现接口的模拟类
问题描述
假设以下场景:我有一个PhoneController
使用类的Phone
类。Phone
是一个继承自抽象类Device
并实现IPhone
接口的类。为了测试PhoneController
我想模拟Phone
类,但我不知道如何使用 NSubstitute 来完成,因为Phone
类继承了抽象类,另外它实现了接口。
示例代码:
public abstract class Device
{
protected string Address { get; set; }
}
public interface IPhone
{
void MakeCall();
}
public class Phone : Device, IPhone
{
public void MakeCall()
{
throw new NotImplementedException();
}
}
public class PhoneController
{
private Phone _phone;
public PhoneController(Phone phone)
{
_phone = phone;
}
}
[TestClass]
public class PhoneControllerTests
{
[TestMethod]
public void TestMethod1()
{
// How mock Phone class?
//var mock = Substitute.For<Device, IPhone>();
//usage of mock
//var controller = new PhoneController(mock);
}
}
第二种情况:
控制器使用抽象类中的GetStatus
方法,因此不能更改为类型Device
_phone
IPhone
public abstract class Device
{
protected string Address { get; set; }
public abstract string GetStatus();
}
public interface IPhone
{
void MakeCall();
}
public class Phone : Device, IPhone
{
public void MakeCall()
{
throw new NotImplementedException();
}
public override string GetStatus()
{
throw new NotImplementedException();
}
}
public class PhoneController
{
private Phone _phone;
public PhoneController(Phone phone)
{
_phone = phone;
}
public string GetDeviceStatus()
{
return _phone.GetStatus();
}
public void MakeCall()
{
_phone.MakeCall();
}
}
[TestClass]
public class PhoneControllerTests
{
[TestMethod]
public void TestMethod1()
{
// How mock Phone class?
//var mock = Substitute.For<Device, IPhone>();
//usage of mock
//var controller = new PhoneController(mock);
}
}
解决方案
有几种方法可以做到这一点,您选择哪一种取决于您要测试的内容。
您可以模拟 iPhone 界面(正如您在注释掉的代码中所做的那样。
您可以子类化电话类(手动或使用 NSubstitute 的
.ForPartsOf<>
)。有关此的博客文章,请参见此处。
我发现如果我使用 Arrange/Act/Assert 方法构建我的测试,那么我要测试的内容会更清楚(理想情况下,您的 Act 部分应该有一个调用;例如:
[TestMethod]
public void TestMethod1()
{
// Arrange
var mock = Substitute.For<IPhone>();
var controller = new PhoneController(mock);
// Act
int result = controller.Method();
// Assert
Assert.Equal(result, 3);
}
编辑 - 基于更新的评论
您不能对抽象类进行单元测试,因为该类不包含(根据定义)任何代码。在您的场景中,看起来您正在尝试做的是测试具体Phone
类。如果是这种情况,那么只需创建Phone
该类的一个实例并对其进行测试;您不需要涉及控制器:
// Arrange
var phone = new Phone();
// Act
string result = phone.GetStatus();
// Assert
Assert.Equal("New", result);
推荐阅读
- javascript - 在视频播放器 VideoJS 中添加质量选择器 JavaScript
- angular - Angular Storybook - WebpackOptionsValidationError:Webpack 已使用与 API 模式不匹配的配置对象进行初始化
- inno-setup - 从 Inno Setup 中的现有文件中删除只读属性
- reactjs - 处于反应状态的数组未正确更新
- xslt - XSL FO 使用border-collapse=separate 丢失表格标题行的样式
- java - Harmony OS 中用于 Android OS 中的 AccelerateInterpolator 和 OvershootInterpolator 的替代类是什么?
- php - Symfony 5.3:http-cache 未处理 ESI 标签
- docker - 删除 Deployment 不会删除 Kubernetes aks 中的副本集/pod
- c++ - mysqlx xdevapi cmake undefined reference 编译错误
- android - Flutter Android 11 权限,例如 WhatsApp