Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否可以使用Activator.CreateInstance()模拟方法?_C#_Unit Testing_Reflection_Moq - Fatal编程技术网

C# 是否可以使用Activator.CreateInstance()模拟方法?

C# 是否可以使用Activator.CreateInstance()模拟方法?,c#,unit-testing,reflection,moq,C#,Unit Testing,Reflection,Moq,我的方法有一个类型参数,所以我在单元测试中试图定义一个mock对象并传递它的一个类型,希望这个类型的实例能够像我定义的那样模拟这个方法。但是,如果我在使用Activator.CreateInstance()创建了一个mock方法之后调用它,我将成为NotImplementedException 是否可以使用Activator.CreateInstance()模拟方法 使用系统; 使用Microsoft.VisualStudio.TestTools.UnitTesting; 使用最小起订量; [测

我的方法有一个类型参数,所以我在单元测试中试图定义一个mock对象并传递它的一个类型,希望这个类型的实例能够像我定义的那样模拟这个方法。但是,如果我在使用Activator.CreateInstance()创建了一个mock方法之后调用它,我将成为NotImplementedException

是否可以使用Activator.CreateInstance()模拟方法

使用系统;
使用Microsoft.VisualStudio.TestTools.UnitTesting;
使用最小起订量;
[测试类]
公共类MyTestClass
{
[测试方法]
public void TestDoFunc()
{
var vmod=新的MyViewModel();
var mock=new mock();
mock.Setup(x=>x.DoInterfaceFunc(vmod)).Callback((viewModel)=>{viewModel.Created=true;})。返回(true);
Assert.IsTrue(mock.Object.DoInterfaceFunc(vmod));//这很有效
Assert.IsTrue(vmod.Created);//这很有效
var mockObjFromActivator=Activator.CreateInstance(mock.Object.GetType())作为IAmAnInterface;
Assert.IsTrue(mockObjFromActivator.DoInterfaceFunc(vmod));//此抛出未实现异常
}
}
公共类MyViewModel{public bool Created{get;set;}}
公共接口IAmAnInterface{bool DoInterfaceFunc(TViewModel vmod);}
编辑:

我想测试这样的功能:

void DoFunc(Type objType)
{
    var vmod = new MyViewModel();
    var objImplInterface = Activator.CreateInstance(objType) as IAmAnInterface<MyViewModel>;
    objImplInterface.DoInterfaceFunc(vmod);
    if (vmod.Created)
    {
        //more logic...
    }
}
void DoFunc(类型objType)
{
var vmod=新的MyViewModel();
var objImplInterface=Activator.CreateInstance(objType)作为IAmAnInterface;
DoInterfaceFunc(vmod);
如果(vmod.Created)
{
//更多的逻辑。。。
}
}

当我阅读你的代码时,我假设你想测试你的
接口。但是,您只能测试作为接口实现的类,因为它包含描述方法应该执行的操作的代码

我建议您从头开始编写测试,并牢记以下几点:当它们是您正在测试的类或方法中的依赖项时,请使用模拟。因为可能很难操纵依赖类(例如返回错误),模拟这些类将使测试方法中可能出现的各种情况变得更容易

我希望下面的例子能更清楚地说明这一点

假设我们有两个类,每个类都有自己的接口:

public interface IFoo {
    string DoFuncX();
}

public class Foo : IFoo
{
    IBar _bar;

    public Foo(IBar bar) {
        _bar = bar;
    }

    public string DoFuncX() {
        try {
            return _bar.DoFuncY();
        } catch (Exception ex) {
            return "ERROR";
        }
    }
}

public interface IBar {
    string DoFuncY();
}

public class Bar : IBar {
    public string DoFuncY() {
        return "bar";
    }
}
我想在类
Foo
中测试
DoFuncX
,当
\u bar.dofuncy
抛出错误时,我希望它进入
catch

Test__Foo_DoFuncX__IBar_Throws_Error() {

    // Arrange
    var mockedIBar = Mock<IBar>();
    mockedIBar.Setup(b => b.DoFuncY()).throw(new Exception("Mocked IBar Throws Errors"));

    // Act
    var foo = new Foo(mockedIBar);
    var result = foo.DoFuncX();

    // Assert
    Assert.Equal(result, "ERROR");
}
Test\uuuuufoo\udofuncx\uuuuuiBar\u抛出错误(){
//安排
var mockedIBar=Mock();
Setup(b=>b.DoFuncY()).throw(新异常(“模拟IBar抛出错误”);
//表演
var foo=新foo(mockedIBar);
var result=foo.DoFuncX();
//断言
断言相等(结果为“错误”);
}

代码可能包含错误,但我认为它清楚地表明了它应该做什么。

您需要摆脱
CreateInstance
调用。显然要做的事情是将
DoFunc
传递给工厂方法,或者/以及
类型
(如果不能直接传递给实例使用):

void DoFunc(Func工厂)
{
var vmod=新的MyViewModel();
var objImplInterface=factory();
DoInterfaceFunc(vmod);
如果(vmod.Created)
{
//更多的逻辑。。。
}
}
当然,您可以安排通过其他方式提供工厂,或者安排依赖注入系统注入实例

这可能意味着必须改变如何创建包含
DoFunc
的内容


例如,您可能会将一个工厂传递给实现
funcy的构造函数,听起来您正在尝试做一件非常奇怪的事情。你想达到什么目标?为什么需要使用
Activator.CreateInstance
创建模拟。你是想测试一个模拟的吗?你为什么要这么做?不,我不想测试模拟。可能是不好的命名。这只是一个抽象的再现错误。还有更复杂的逻辑。我希望测试DoFunc(类型objType){var vmod=new MyViewModel();var objImplInterface=Activator.CreateInstance(objType)作为IAmAnInterface;objImplInterface.DoInterfaceFunc(vmod);if(vmod.Created)…更多逻辑}听起来您需要一个工厂来创建传递到
DoFunc
方法的类型实例,该方法使用
Activator.CreateInstance
。您是否可以更改实现?如果是这样的话,我可以告诉你怎么做。否则我认为你不可能用
Moq
实现你想要的,因为你无法控制如何创建模拟。我建议您为一个测试创建
IAmAnInterface
的自定义假实现,并通过它的输入。您可以编写您希望它具有的行为以进行测试。这是一个解决方法-创建自定义虚拟实现,但我希望使用Mock避免它。如果您将public Foo(Type typeOfbar){u bar=Activator.CreateInstance(typeOfbar)作为IBar;}和许多Bar1…BarN,哪种实现IBar?当您传递一个对象时,这也应该起作用,但您将无法模拟,至少不能使用moq(应该可以使用Typemock)。除此之外,我不建议基于Activator方法中的类型创建实例。您可以给出像
IBar bar1=new bar1()这样的对象,而不是将Type作为参数;Foo(bar1);IBar2 bar2=新的bar2();Foo(bar2);IBar谷仓=新谷仓();富(谷仓)。因为类Bar1、Bar2的接口。。。谷仓是IBar。如果需要动态创建,您可以使用依赖项注入。谢谢,hakany,但我需要使用这种方式-类型作为参数,因为程序的其他部分有限制。Andrii提供了一个解决方案——制作一个定制的虚拟实现,我希望通过Mock避免这种情况。
DoFunc
在ViewModel中,而
objType
在XAML(视图)中设置。
Test__Foo_DoFuncX__IBar_Throws_Error() {

    // Arrange
    var mockedIBar = Mock<IBar>();
    mockedIBar.Setup(b => b.DoFuncY()).throw(new Exception("Mocked IBar Throws Errors"));

    // Act
    var foo = new Foo(mockedIBar);
    var result = foo.DoFuncX();

    // Assert
    Assert.Equal(result, "ERROR");
}
void DoFunc(Func<IAmAnInterface<MyViewModel>> factory)
{
    var vmod = new MyViewModel();
    var objImplInterface = factory();
    objImplInterface.DoInterfaceFunc(vmod);
    if (vmod.Created)
    {
        //more logic...
    }
}