C# 是否可以使用Activator.CreateInstance()模拟方法?
我的方法有一个类型参数,所以我在单元测试中试图定义一个mock对象并传递它的一个类型,希望这个类型的实例能够像我定义的那样模拟这个方法。但是,如果我在使用Activator.CreateInstance()创建了一个mock方法之后调用它,我将成为NotImplementedException 是否可以使用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; 使用最小起订量; [测
使用系统;
使用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...
}
}