您如何为单元测试定下一个班级 [英] How do you moq a class for unit test

查看:58
本文介绍了您如何为单元测试定下一个班级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题是对问了最初的问题后,我现在创建了一个最小,完整和可验证的示例,用作该问题的基础.

Since asking the original question I have now created a Minimal, Complete and Verifiable Example which is used as the basis for this question.

我有一个控制器(如下所示)

I have a controller (shown below)

public class HomeController : Controller
{
    private OrganisationLogic _organisationLogic;

    public HomeController(OrganisationLogic logic)
    {
       _organisationLogic = new OrganisationLogic();
    }

    public ActionResult Index()
    {
        var model = _organisationLogic.GetOrganisation().ToViewModel();
        return View(model);
    }
}

控制器从业务逻辑层中称为OrganisationLogic的方法中检索数据(如下所示)

The controller retrieves data from a method in a Business Logic Layer called OrganisationLogic (shown below)

 public class OrganisationLogic : LogicRepository<OrganisationModel>
 {
     public OrganisationLogic()
     {

     }

     public override OrganisationModel GetOrganisation()
     {

         return new OrganisationModel { Id = 1, OrganisationName = "My Orgaisation", Address = "Logic" };

     }
}

稍后,业务逻辑将继承逻辑存储库(如下所示)

The business logic later inherits Logic repository (shown below)

public abstract class LogicRepository<T> : ILogicRepository<T>
{

    protected LogicRepository()
    {

    }


    public abstract T GetOrganisation();

 }

逻辑存储库实现ILogicRepository接口(如下所示)

The Logic Repository implements the ILogicRepository Interface (shown below)

public interface ILogicRepository<TModel>
{
    TModel GetOrganisation();
}

我想对HomeController进行单元测试,以验证ViewModel中显示的数据是否已从OrganisationLogic正确返回并已从OrganisationModel转换为OrganisationViewModel.

I want to Unit Test the HomeController to verify that the data displayed in the ViewModel is returned correctly from OrganisationLogic and Transformed from OrganisationModel into an OrganisationViewModel.

我编写了下面的UnitTest,它使用Moq模拟方法_OrganisationLogic.GetOrganisation().

I have written the following UnitTest which uses Moq to mock the method _OrganisationLogic.GetOrganisation().

[TestMethod]
public void Index()
{

    var _OrganisationLogic = new Mock<OrganisationLogic>();

    var testdata = new OrganisationModel { Id = 3, OrganisationName = "My Test Class Organisation" };

    _OrganisationLogic.Setup(p => p.GetOrganisation()).Returns(testdata).Callback<OrganisationModel>(p=>p = testdata);

    HomeController controller = new HomeController(_OrganisationLogic.Object);
    ViewResult result = controller.Index() as ViewResult;
    OrganisationViewModel model = (OrganisationViewModel)result.Model; 

    Assert.AreEqual(testdata.OrganisationName,model.OrganisationName);
}

运行测试时,测试失败.这是因为Mock并没有覆盖该类,而是从BusinessLogic层中的实际方法返回了结果.

When I run the test the test fails. The reason for this is that the Mock has not overridden the class and has instead returned the result from the actual method in the BusinessLogic Layer.

在我最初的问题中,我发帖说正在生成的错误消息是:

In my original question I posted that the error message being generated was:

System.ArgumentException无效的回调.参数为0的方法上的设置无法调用具有不同数量的参数(1)的回调. Source = Moq StackTrace:位于Moq.MethodCallReturn2.ValidateNumberOfCallbackParameters(MethodInfo Moq.MethodCallReturn2.ValidateReturnDelegate(Delegate回调)处于Moq.MethodCallReturn2.Returns [T](Func2 valueExpression)

System.ArgumentException Invalid callback. Setup on method with 0 parameter(s) cannot invoke callback with different number of parameters (1). Source=Moq StackTrace: at Moq.MethodCallReturn2.ValidateNumberOfCallbackParameters(MethodInfo callbackMethod) at Moq.MethodCallReturn2.ValidateReturnDelegate(Delegate callback) at Moq.MethodCallReturn2.Returns[T](Func2 valueExpression)

我现在已经能够通过运行以下单元测试来完全复制此错误消息.我怀疑上面的单元测试更接近我的需求,而在下面的实例中,我错误地设置了Return().欢迎对此有想法吗?

I have now been able to replicate this error message exactly by running the following Unit Test. I suspect the unit test above is closer to what I need and that in the instance below I am setting up the Return() incorrectly. Thoughts on this are welcome?

[TestMethod]
public void Index()
{

     var _OrganisationLogic = new Mock<OrganisationLogic>();

     var testdata = new OrganisationModel { Id = 3, OrganisationName = "My Test Class Organisation" };

     _OrganisationLogic.Setup(p => p.GetOrganisation()).Returns<OrganisationModel>(p=>p = testdata).Callback<OrganisationModel>(p=>p = testdata);

     HomeController controller = new HomeController(_OrganisationLogic.Object);
     ViewResult result = controller.Index() as ViewResult;
     OrganisationViewModel model = (OrganisationViewModel)result.Model; 

     Assert.AreEqual(testdata.OrganisationName,model.OrganisationName);
}

我的问题是如何设置Mock,以便它使用我的测试数据.

My question is how to I setup the Mock so that it uses my test data.

为了帮助回答上述问题,我在GitHub上放置了一个版本的Code,以演示此问题并显示测试失败.可以通过 https://github.com/stephenwestgarth/UnitTestExample

In order to assist with answering the the above I have placed a version of the Code on GitHub that demonstrates this issue and shows the test failing. This can be accessed at https://github.com/stephenwestgarth/UnitTestExample

任何帮助将不胜感激.

推荐答案

更改HomeController的构造函数,以使参数类型为ILogicRepository<OrganisationModel>,并且该字段也将需要该类型,并使用注入到其中的实例构造函数. _organisationLogic = logic;(上面的代码将忽略该参数,并创建其自己的OrganisationLogic具体实例,这意味着它没有使用您的模拟对象.

Change the constructor of HomeController so that the parameter type is ILogicRepository<OrganisationModel>, and the field will need that type as well, and use the instance that was injected into the constructor. _organisationLogic = logic; (your code above ignores the parameter and creates its own concrete instance of the OrganisationLogic, which means it is not using your mock object.

在测试中,将_OrganisationLogic的声明更改为... var _OrganisationLogic = new Mock<ILogicRepository<OrganisationModel>>();

In the test change the declaration of _OrganisationLogic to be... var _OrganisationLogic = new Mock<ILogicRepository<OrganisationModel>>();

正如我之前问过的那样,我认为您不需要在其中使用回调.

As I said when you previously asked, I don't think you need that Callback in there.

编辑后的构造函数看起来像这样...

Edited constructor would look like this...

private ILogicRepository<OrganisationModel> _organisationLogic;

public HomeController(ILogicRepository<OrganisationModel> logic)
{
   _organisationLogic = logic;
}

这篇关于您如何为单元测试定下一个班级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆