如何将模拟对象分配给控制器中的对象?

时间:2015-12-22 10:11:05

标签: c# unit-testing asp.net-mvc-4 moq

我有一个控制器,其中包含一个business类,内部具有datahandler的依赖关系。为了测试该业务类,我需要模拟datahandler。设置完成后,我正在分配商务课程' datahandler与模拟datahandler。但在调试时,商务舱' datahandler显示为null,我知道我应该使用构造函数来注入模拟对象。但是可以在不使用任何构造函数注入的情况下执行它吗?任何正文可以帮助我吗?

我的商务舱:

public class FooBusiness
{
  public static BarDataHandler _barDatahandler = new BarDataHandler();
  ...
}

测试类:

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
    ...
   }
}

2 个答案:

答案 0 :(得分:0)

您需要将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 )来模拟单元测试中的IBarDataHandler虚假实现。

答案 1 :(得分:0)

正如我所提到的,有多种方法可以满足您的需求。 我个人更喜欢Shyju的答案(构造函数注入),但如果你不能改变构造函数,你仍然可以通过设置属性来改变实现:

商务舱:

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
    }
}

如果您担心重构实现,最好先设置所有测试。之后你可以用更安全的感觉重构:)