如何将模拟对象分配给控制器中的对象?
How to assign a mocked object to a object in controller?
我有一个包含 business
class 的控制器,它在内部依赖于 datahandler
。为了测试该业务 class,我需要模拟 datahandler
。设置后,我将业务 class' datahandler
分配给模拟 datahandler
。但是在调试时,业务 class' datahandler
显示 null ,我知道我应该使用构造函数来注入模拟的 object.But 是否可以在不使用任何构造函数注入的情况下做到这一点?任何人都可以帮助我吗?
我的公司class:
public class FooBusiness
{
public static BarDataHandler _barDatahandler = new BarDataHandler();
...
}
测试class:
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
...
}
}
您需要将 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
class 添加构造函数,它接受 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 在您的单元测试中模拟 IBarDataHandler 的假实现。
正如我提到的,有多种方法可以满足您的需求。
我个人更喜欢 Shyju 的回答(构造函数注入),但是如果你不能更改构造函数,你仍然可以通过设置 属性:
来更改实现
业务class:
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);
}
}
测试class:
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
}
}
如果您担心重构实现,最好先设置所有测试。之后你可以带着更安全的感觉重构 :)
我有一个包含 business
class 的控制器,它在内部依赖于 datahandler
。为了测试该业务 class,我需要模拟 datahandler
。设置后,我将业务 class' datahandler
分配给模拟 datahandler
。但是在调试时,业务 class' datahandler
显示 null ,我知道我应该使用构造函数来注入模拟的 object.But 是否可以在不使用任何构造函数注入的情况下做到这一点?任何人都可以帮助我吗?
我的公司class:
public class FooBusiness
{
public static BarDataHandler _barDatahandler = new BarDataHandler();
...
}
测试class:
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
...
}
}
您需要将 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
class 添加构造函数,它接受 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 在您的单元测试中模拟 IBarDataHandler 的假实现。
正如我提到的,有多种方法可以满足您的需求。 我个人更喜欢 Shyju 的回答(构造函数注入),但是如果你不能更改构造函数,你仍然可以通过设置 属性:
来更改实现业务class:
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);
}
}
测试class:
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
}
}
如果您担心重构实现,最好先设置所有测试。之后你可以带着更安全的感觉重构 :)