如何将接口类型转换为具体类型
本文关键字:类型 类型转换 接口 | 更新日期: 2023-09-27 18:09:01
我试图模拟ManagementObjectSearcher
类并创建了IManagementInfo
接口,那么我如何将接口转换为ManagementObjectSearcher
类呢?
ManagementObjectSearcher s = new ManagementObjectSearcher();
IManagementInfo info = s as IManagementInfo;
创建一个空信息对象
ManagementObjectSearcher s = new ManagementObjectSearcher();
IManagementInfo info =IManagementInfo(s);
这给了我运行时错误(不能类型转换)
你不能那样做。您想这样做是为了编写单元测试吗?如果你试图模拟一个你无法控制的类,那么你必须把它包装在另一个类中。
public class MyManagementObjectSearcherWrapper : IManagementInfo
{
public void TheMethodToMock()
{
var searcher = new ManagementObjectSearcher();
// The code you want to mock goes here
}
}
你像这样运行你的代码:
public void YourCode(IManagementInfo info)
{
info.TheMethodToMock();
}
那么YourCode()将接受您的包装器或模拟对象。您可以使用IManagementInfo
接口创建mock。
看起来好像你试图包装一个第三方/系统对象,以帮助单元测试。
说你的起点是
public class Dependency {
public string Foo() {
return "foo"; // machine, system, time, something else, dependent result
}
public string Bar() {
return "bar";
}
}
public class MySimpleClass {
public string MyFunc() {
return new Dependency().Foo();
}
}
[TestMethod]
public void TestSimple() {
var client = new MySimpleClass();
Assert.AreEqual("foo", client.MyFunc());
}
我们在调用中创建依赖,因为我们认为创建成本没有保持依赖的实例重要。这要视情况而定。我们也可以很容易地在actor中创建一个Dependency,并存储一个副本,以便每次调用。无论哪种方式,我们都无法控制输出,这使得单元测试变得混乱。
我们需要为它创建一个代理。
1。为需要的成员定义一个接口
最有可能的是,我们不需要使用包装的所有成员,所以只在接口中包含我们关心的那些成员。
public interface IDependencyProxy {
string Foo();
}
2。创建代理类
然后,我们创建一个代理类,包装依赖项和实现接口。同样,我们可以在开始时或在逐个调用的基础上创建。
public class DependencyProxy : IDependencyProxy {
public string Foo() {
return new Dependency.Foo();
}
}
3。根据接口
定义客户端代码我们稍微修改了客户端代码,以使用IDependencyProxy接口而不是Dependency。有几种方法可以做到这一点。我通常使用内部变量,它从公共变量中获取依赖链。(使用[InternalsVisibleTo]允许单元测试看到它)
public class MyRevisedClass {
private readonly IDependencyProxy dependency;
public MyRevisedClass()
: this( new DependencyProxy()) {}
internal MyRevisedClass(IDependencyProxy dependency) {
this.dependency = dependency;
}
public string MyFunc() {
return dependency.Foo();
}
}
这允许我们为生产代码设置默认行为(调用System对象),并允许我们模拟出单元测试的结果。
[TestMethod]
public void TestRevisedDefault() {
var client = new MyRevisedClass();
Assert.AreEqual("foo", client.MyFunc());
}
[TestMethod]
public void TestRevisedWithMockedDependency() {
var dep = new Mock<IDependencyProxy>();
dep.Setup(mk => mk.Foo()).Returns("bar");
var client = new MyRevisedClass(dep.Object);
Assert.AreEqual("bar", client.MyFunc());
}