C# 如何将模拟对象分配给控制器中的对象?
我有一个控制器,它包含一个C# 如何将模拟对象分配给控制器中的对象?,c#,unit-testing,asp.net-mvc-4,moq,C#,Unit Testing,Asp.net Mvc 4,Moq,我有一个控制器,它包含一个业务类,该类在内部依赖于数据处理程序。为了测试该业务类,我需要模拟datahandler。安装后,我将使用模拟的数据处理程序分配业务类'datahandler。但是在调试时,业务类“datahandler显示为null,我知道我应该使用构造函数来注入模拟对象。但是不使用任何构造函数注入是否可以做到这一点?有人能帮我吗 我的商务舱: public class FooBusiness { public static BarDataHandler _barDatahand
业务
类,该类在内部依赖于数据处理程序
。为了测试该业务类,我需要模拟datahandler
。安装后,我将使用模拟的数据处理程序
分配业务类'datahandler
。但是在调试时,业务类“datahandler
显示为null,我知道我应该使用构造函数来注入模拟对象。但是不使用任何构造函数注入是否可以做到这一点?有人能帮我吗
我的商务舱:
public class FooBusiness
{
public static BarDataHandler _barDatahandler = new BarDataHandler();
...
}
public class FooBusiness
{
private IBarDataHandler _barDatahandler = new BarDatahandler();
public IBarDataHandler BarDatahandler
{
get { return _barDatahandler; }
set { _barDatahandler = value; }
}
public int Search(int a)
{
return _barDatahandler.Search(a);
}
}
测试等级:
public class FooBusinessTest
{
...
_mockedBarDataHandler = new Mock<IBarDataHandler>(){CallBase:true};
public FooTestMeth()
{
//Arrange
_mockedBarDataHandler.Setup(x=>x.Search(It.IsAny<int>).Returns(1);
...
FooBusiness _fooBusiness = new FooBusiness();
FooBusiness._barDatahandler = _mockedBarDataHandler.Object;
//Act
...
}
}
public class FooBusinessTest
{
_mockedBarDataHandler = new Mock<IBarDataHandler>(){CallBase:true};
public FooTestMeth()
{
//Arrange
_mockedBarDataHandler.Setup(x => x.Search(It.IsAny<int>).Returns(1);
FooBusiness fooBusiness = new FooBusiness();
fooBusiness.BarDatahandler = _mockedBarDataHandler.Object;
//Act
}
}
公共类测试
{
...
_mockedBarDataHandler=new Mock(){CallBase:true};
公共足球方法()
{
//安排
_Setup(x=>x.Search(It.IsAny).Returns(1);
...
FooBusiness_FooBusiness=新的FooBusiness();
FooBusiness.\u barDatahandler=\u mockedBarDataHandler.Object;
//表演
...
}
}
您需要将dataHandler依赖项注入到FooBusiness
如果不存在BarDataHandler
,则需要为其提取接口
interface IBarDataHandler
{
string GetUserToken(int id);
}
public class BarDataHandler : IBarDataHandler
{
public string GetUserToken(int id)
{
// to do :read from db and return
}
}
并将构造函数添加到FooBusiness
类中,该类接受IBarDataHandler
的实现
public class FooBusiness
{
IBarDataHandler barDataHandler;
public FooBusiness(IBarDataHandler barDataHandler)
{
this.barDataHandler=barDataHandler
}
public string GetUserToken(int id)
{
return this.barDataHandler.GetUserToken(id);
}
}
当应用程序运行时,您可以使用Unity/Ninject/StructureMap等任何一种依赖注入框架来解决具体的实现问题
您可以使用任何模拟框架,如Moq在unittests中模拟IBarDataHandler的伪实现。如我所述,有多种方法可以满足您的需求。 就我个人而言,我更喜欢Shyju的答案(构造函数注入),但是如果您不能更改构造函数,您仍然可以在以后通过设置属性来更改实现: 商务舱:
public class FooBusiness
{
public static BarDataHandler _barDatahandler = new BarDataHandler();
...
}
public class FooBusiness
{
private IBarDataHandler _barDatahandler = new BarDatahandler();
public IBarDataHandler BarDatahandler
{
get { return _barDatahandler; }
set { _barDatahandler = value; }
}
public int Search(int a)
{
return _barDatahandler.Search(a);
}
}
测试等级:
public class FooBusinessTest
{
...
_mockedBarDataHandler = new Mock<IBarDataHandler>(){CallBase:true};
public FooTestMeth()
{
//Arrange
_mockedBarDataHandler.Setup(x=>x.Search(It.IsAny<int>).Returns(1);
...
FooBusiness _fooBusiness = new FooBusiness();
FooBusiness._barDatahandler = _mockedBarDataHandler.Object;
//Act
...
}
}
public class FooBusinessTest
{
_mockedBarDataHandler = new Mock<IBarDataHandler>(){CallBase:true};
public FooTestMeth()
{
//Arrange
_mockedBarDataHandler.Setup(x => x.Search(It.IsAny<int>).Returns(1);
FooBusiness fooBusiness = new FooBusiness();
fooBusiness.BarDatahandler = _mockedBarDataHandler.Object;
//Act
}
}
公共类测试
{
_mockedBarDataHandler=new Mock(){CallBase:true};
公共足球方法()
{
//安排
_Setup(x=>x.Search(It.IsAny).Returns(1);
FooBusiness=newfoobusiness();
fooBusiness.BarDatahandler=\u mockedBarDataHandler.Object;
//表演
}
}
如果您担心重构实现,最好先设置所有测试。然后您可以更安全地重构:)构造函数注入是一种方法,但您也可以设置属性。我不喜欢这样,但这是另一个问题。您需要删除static关键字,并且_barDatahandler应为IBarDataHandler类型。应按预期工作……您希望此公共字段为静态字段有什么原因吗?@Marc:很久以前没有人编写过此代码,我也没有不应该改变商业课程。你为什么不把这个写在答案里,这样我就可以接受呢?我把我的答案贴出来了。如果你想的话,你可以标记为已回答。