简体   繁体   English

如何将强制类型转换为接口

[英]How to type cast interface to a concrete type

I am trying to mock the ManagementObjectSearcher class and have created a IManagementInfo interface, so how can i cast the interface to the ManagementObjectSearcher class? 我试图模拟ManagementObjectSearcher类并创建了一个IManagementInfo接口,那么我如何将接口转换为ManagementObjectSearcher类?

 ManagementObjectSearcher s = new ManagementObjectSearcher();
 IManagementInfo info = s as IManagementInfo;

this creates me a null info object 这创建了一个空信息对象

ManagementObjectSearcher s = new ManagementObjectSearcher();
 IManagementInfo info =IManagementInfo(s);

this gives me run time error (cannot typecast) 这给了我运行时错误(不能强制转换)

You cannot do that. 你不能这样做。 Do you want to do it so that you can write unit tests? 你想这样做,你可以编写单元测试吗? If you are trying to mock a class that you have no control of, then you have to wrap it in another class. 如果你试图模拟一个你无法控制的类,那么你必须将它包装在另一个类中。

public class MyManagementObjectSearcherWrapper : IManagementInfo
{
    public void TheMethodToMock()
    {
        var searcher = new ManagementObjectSearcher();        
        // The code you want to mock goes here
    }
}

And you run your code like this: 你运行你的代码是这样的:

public void YourCode(IManagementInfo info)
{
    info.TheMethodToMock();
}

Then YourCode() will take either your wrapper or the mocked object. 然后,YourCode()将获取您的包装器或模拟对象。 You create your mock using the IManagementInfo interface. 您可以使用IManagementInfo界面创建模拟。

It looks as if you are trying to wrap a 3rd party/system object in order to aid unit testing. 看起来好像是在尝试包装第三方/系统对象以帮助进行单元测试。

Say that your starting point is 说你的出发点是

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());

}

We are creating the Dependency inside the call because we are considering the creation cost to be less important than holding on to an instance of the Dependency. 我们在调用中创建了Dependency,因为我们正在考虑创建成本不如持有Dependency实例那么重要。 This will be dependent upon the situation. 这取决于具体情况。 We could as easily have created a Dependency in the ctor and stored a copy which we invoked each time. 我们可以很容易地在ctor中创建一个Dependency并存储我们每次调用的副本。 Either way, we have no control over the output which makes unit testing messy. 无论哪种方式,我们都无法控制输出,这使得单元测试变得混乱。

We need to create a proxy for it. 我们需要为它创建一个代理。

1. Define an interface for the members that we need 1.为我们需要的成员定义一个接口
Most likely, we do not need to use all of the members of the wrappee so only include in the interface those about which we care. 最有可能的是,我们不需要使用包装的所有成员,因此只在接口中包含我们关心的那些成员。

public interface IDependencyProxy {
    string Foo();
}

2. Create a Proxy Class 2.创建代理类
We then create a proxy class wrapping the dependency and implementing interface. 然后,我们创建一个包含依赖项和实现接口的代理类。 Again, we can create at start or on a call by call basis. 同样,我们可以在开始时或逐个呼叫的基础上创建。

public class DependencyProxy : IDependencyProxy {

    public string Foo() {
        return new Dependency.Foo();
    }

}

3. Define our client code in terms of the interface 3.根据界面定义客户端代码
We modify our client code slightly to use the IDependencyProxy interface instead of the Dependency. 我们稍微修改我们的客户端代码以使用IDependencyProxy接口而不是Dependency。 There are a few ways of doing this. 有几种方法可以做到这一点。 I generally use an internal ctor which takes the dependency chained from a public ctor. 我通常使用一个内部ctor,它接受来自公共ctor的链接。 (Use [InternalsVisibleTo] to allow the unit tests to see it) (使用[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();
    }

}

This allows us a default behaviour for the production code (invokes the System object) and allows us to mock out the results for unit testing. 这允许我们生产代码的默认行为(调用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());

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM