Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将模拟对象分配给控制器中的对象?_C#_Unit Testing_Asp.net Mvc 4_Moq - Fatal编程技术网

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:很久以前没有人编写过此代码,我也没有不应该改变商业课程。你为什么不把这个写在答案里,这样我就可以接受呢?我把我的答案贴出来了。如果你想的话,你可以标记为已回答。