[英]Is it possible to mock a method with using of Activator.CreateInstance()?
My method has a type parameter, so I am trying in my unit test to define a mock object and pass a type of it with a hope, that the instance of this type will mock the method as I have defined it. 我的方法有一个类型参数,因此我在单元测试中尝试定义一个模拟对象并传递其类型,希望这种类型的实例可以像我定义的那样模拟该方法。 But if I call a method of my mock after I have created it with Activator.CreateInstance(), I become NotImplementedException.
但是,如果使用Activator.CreateInstance()创建模拟的方法后调用它的方法,则将成为NotImplementedException。
Is it possible to mock a method with using of Activator.CreateInstance()? 是否可以使用Activator.CreateInstance()模拟方法?
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
[TestClass]
public class MyTestClass
{
[TestMethod]
public void TestDoFunc()
{
var vmod = new MyViewModel();
var mock = new Mock<IAmAnInterface<MyViewModel>>();
mock.Setup(x => x.DoInterfaceFunc(vmod)).Callback<MyViewModel>((viewModel) => { viewModel.Created = true; }).Returns(true);
Assert.IsTrue(mock.Object.DoInterfaceFunc<MyViewModel>(vmod));//this works
Assert.IsTrue(vmod.Created);//this works
var mockObjFromActivator = Activator.CreateInstance(mock.Object.GetType()) as IAmAnInterface<MyViewModel>;
Assert.IsTrue(mockObjFromActivator.DoInterfaceFunc<MyViewModel>(vmod));//this throw NotImplementedException
}
}
public class MyViewModel { public bool Created { get; set; } }
public interface IAmAnInterface<TViewModel> { bool DoInterfaceFunc<TViewModel>(TViewModel vmod); }
EDIT: 编辑:
I want to test such function: 我想测试这样的功能:
void DoFunc(Type objType)
{
var vmod = new MyViewModel();
var objImplInterface = Activator.CreateInstance(objType) as IAmAnInterface<MyViewModel>;
objImplInterface.DoInterfaceFunc(vmod);
if (vmod.Created)
{
//more logic...
}
}
When I read your code I assume you want to test your IAmAnInterface
interface. 当我阅读您的代码时,我假设您想测试
IAmAnInterface
接口。 However you can only test a class which is an implementation of the interface because it contains code which describes what your method should do. 但是,您只能测试作为接口实现的类,因为它包含描述您的方法应该执行的代码。
I would recommend your to write your test from scratch with the following in mind: use mocking when their are dependencies in your class or method which you are testing. 我建议您从头开始编写测试,并牢记以下几点:当模拟是您要测试的类或方法中的依赖项时,请使用模拟。 Because it could be hard to manipulate the depended class for example to return an error, mocking those will make it easier to test various situations which can occur in your method.
因为可能很难操纵依赖类,例如返回错误,所以对它们进行模拟将使测试方法中可能发生的各种情况变得更加容易。
I hope the example below would make it more clear. 我希望下面的例子可以使它更加清楚。
Let say we have 2 classes with each their own interface: 假设我们有2个类,每个类都有自己的接口:
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";
}
}
and I want to test DoFuncX
in class Foo
and I expect that it enters in catch
when _bar.DoFunctY
throws an error: 我想在
Foo
类中测试DoFuncX
,并且我希望它在_bar.DoFunctY
引发错误时进入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");
}
code can contains errors, but I think it makes clear what it should do. 代码可以包含错误,但是我认为它可以清楚地说明应该做什么。
You need to get rid of the CreateInstance
call. 您需要摆脱
CreateInstance
调用。 The obvious thing to do is to have DoFunc
be passed a factory method instead or/as well as the Type
(if it can't be passed the instance to use directly): 显而易见的事情是让
DoFunc
传递给工厂方法代替,或者传递给Type
(以及Type
(如果不能传递给实例直接使用):
void DoFunc(Func<IAmAnInterface<MyViewModel>> factory)
{
var vmod = new MyViewModel();
var objImplInterface = factory();
objImplInterface.DoInterfaceFunc(vmod);
if (vmod.Created)
{
//more logic...
}
}
Of course, you may be able to arrange for the factory to be supplied via other means, or for the instance to use to be injected by a dependency injection system. 当然,您也许可以安排通过其他方式为工厂提供服务,或者通过依赖项注入系统来注入实例。
This may mean changes, in turn, for how whatever contains DoFunc
has to be created. 不管如何包含这可能意味着改变,反过来,对于
DoFunc
必须创建。
Eg you may instead have a factory passed to the constructor that implements Func<Type, IAmAnInterface<MyViewModel>
and you then later use that in DoFunc
, and of course provide a mock during testing that hands back the mocked interface. 例如,您可能改为将工厂传递给实现
Func<Type, IAmAnInterface<MyViewModel>
的构造函数,然后再在DoFunc
使用它,并且在测试过程中当然要提供一个模拟,以将模拟接口DoFunc
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.