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

时间:2013-04-12 09:14:14

标签: c# unit-testing

我正在尝试模拟ManagementObjectSearcher类并创建了一个IManagementInfo接口,那么我如何将接口转换为ManagementObjectSearcher类?

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

这会创建一个空信息对象

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

这给了我运行时错误(不能强制转换)

2 个答案:

答案 0 :(得分:4)

你做不到。你想这样做,你可以编写单元测试吗?如果你试图模拟一个你无法控制的类,那么你必须把它包装在另一个类中。

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界面创建模拟。

答案 1 :(得分:0)

看起来您正在尝试包装第三方/系统对象以帮助进行单元测试。

说你的出发点是

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

}

我们正在调用内部创建依赖项,因为我们正在考虑创建成本不如持有依赖项实例那么重要。这取决于具体情况。我们可以很容易地在ctor中创建一个Dependency并存储我们每次调用的副本。无论哪种方式,我们都无法控制输出,这使得单元测试变得混乱。

我们需要为它创建一个代理。

<强> 1。为我们需要的成员定义一个界面
最有可能的是,我们不需要使用包装的所有成员,因此只在接口中包含我们关心的那些成员。

public interface IDependencyProxy {
    string Foo();
}

<强> 2。创建代理类
然后,我们创建一个包含依赖项和实现接口的代理类。同样,我们可以在开始时或逐个呼叫的基础上创建。

public class DependencyProxy : IDependencyProxy {

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

}

第3。根据界面定义我们的客户代码 我们稍微修改我们的客户端代码以使用IDependencyProxy接口而不是Dependency。有几种方法可以做到这一点。我通常使用一个内部ctor,它接受来自公共ctor的链接。 (使用[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());

}