C# 你如何为单元测试设计一门课
此问题作为后续问题发布 自从提出最初的问题以来,我现在创建了一个最小的、完整的和可验证的示例,作为这个问题的基础 我有一个控制器如下所示C# 你如何为单元测试设计一门课,c#,asp.net-mvc,unit-testing,mocking,moq,C#,Asp.net Mvc,Unit Testing,Mocking,Moq,此问题作为后续问题发布 自从提出最初的问题以来,我现在创建了一个最小的、完整的和可验证的示例,作为这个问题的基础 我有一个控制器如下所示 public class HomeController : Controller { private OrganisationLogic _organisationLogic; public HomeController(OrganisationLogic logic) { _organisationLogic = ne
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);
}
}
public class OrganisationLogic : LogicRepository<OrganisationModel>
{
public OrganisationLogic()
{
}
public override OrganisationModel GetOrganisation()
{
return new OrganisationModel { Id = 1, OrganisationName = "My Orgaisation", Address = "Logic" };
}
}
public abstract class LogicRepository<T> : ILogicRepository<T>
{
protected LogicRepository()
{
}
public abstract T GetOrganisation();
}
public interface ILogicRepository<TModel>
{
TModel GetOrganisation();
}
控制器从名为OrganizationLogic的业务逻辑层中的方法检索数据,如下所示
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);
}
}
public class OrganisationLogic : LogicRepository<OrganisationModel>
{
public OrganisationLogic()
{
}
public override OrganisationModel GetOrganisation()
{
return new OrganisationModel { Id = 1, OrganisationName = "My Orgaisation", Address = "Logic" };
}
}
public abstract class LogicRepository<T> : ILogicRepository<T>
{
protected LogicRepository()
{
}
public abstract T GetOrganisation();
}
public interface ILogicRepository<TModel>
{
TModel GetOrganisation();
}
业务逻辑稍后继承如下所示的逻辑存储库
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);
}
}
public class OrganisationLogic : LogicRepository<OrganisationModel>
{
public OrganisationLogic()
{
}
public override OrganisationModel GetOrganisation()
{
return new OrganisationModel { Id = 1, OrganisationName = "My Orgaisation", Address = "Logic" };
}
}
public abstract class LogicRepository<T> : ILogicRepository<T>
{
protected LogicRepository()
{
}
public abstract T GetOrganisation();
}
public interface ILogicRepository<TModel>
{
TModel GetOrganisation();
}
逻辑存储库实现如下所示的ILogicRecepository接口
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);
}
}
public class OrganisationLogic : LogicRepository<OrganisationModel>
{
public OrganisationLogic()
{
}
public override OrganisationModel GetOrganisation()
{
return new OrganisationModel { Id = 1, OrganisationName = "My Orgaisation", Address = "Logic" };
}
}
public abstract class LogicRepository<T> : ILogicRepository<T>
{
protected LogicRepository()
{
}
public abstract T GetOrganisation();
}
public interface ILogicRepository<TModel>
{
TModel GetOrganisation();
}
我想对HomeController进行单元测试,以验证ViewModel中显示的数据是否正确地从OrganizationLogic返回,并从OrganizationModel转换为OrganizationViewModel
我编写了以下UnitTest,它使用Moq模拟方法&u OrganizationLogic.getOrganization
[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层中的实际方法返回结果
在我最初的问题中,我发布的错误消息是:
System.ArgumentException无效回调。具有0个参数的方法上的安装程序无法使用不同数量的参数1调用回调。Source=Moq StackTrace:at Moq.MethodCallReturn2.ValidateNumberOfCallbackParametersMethodInfo
Moq.MethodCallReturn2.ValidateReturnDelegateDelegateDelegate调用Moq.MethodCallReturn2.Returns[T]Func2值表达式
我现在能够通过运行下面的单元测试准确地复制这个错误消息。我怀疑上面的单元测试更接近我所需要的,在下面的例子中,我设置的返回错误。欢迎对此发表意见
[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,以便它使用我的测试数据
为了帮助回答上述问题,我在GitHub上放置了一个版本的代码,它演示了这个问题,并显示测试失败。可访问以下网址:
非常感谢您的帮助。更改HomeController的构造函数,使参数类型为ILogicRespository,字段也需要该类型,并使用注入构造函数的实例_组织逻辑=逻辑;上面的代码忽略了参数,并创建了OrganizationLogic自己的具体实例,这意味着它没有使用模拟对象 在测试中,将组织逻辑的声明更改为。。。 var _OrganizationLogic=新模拟 正如我之前问过的,我认为你不需要回电话 编辑的构造函数将如下所示
private ILogicRepository<OrganisationModel> _organisationLogic;
public HomeController(ILogicRepository<OrganisationModel> logic)
{
_organisationLogic = logic;
}
更改HomeController的构造函数,使参数类型为ILogicRepository,字段也需要该类型,并使用注入构造函数的实例_组织逻辑=逻辑;上面的代码忽略了参数,并创建了OrganizationLogic自己的具体实例,这意味着它没有使用模拟对象 在测试中,将组织逻辑的声明更改为。。。 var _OrganizationLogic=新模拟 正如我之前问过的,我认为你不需要回电话 编辑的构造函数将如下所示
private ILogicRepository<OrganisationModel> _organisationLogic;
public HomeController(ILogicRepository<OrganisationModel> logic)
{
_organisationLogic = logic;
}
请你改变我的构造器上面,并张贴完成的构造器?我很难理解你的所有建议:我已经取消了回调,我得到了相同的错误是的,因为在返回代码部分失败,在它到达回调之前。太好了!考试通过了!谢谢你的帮助!对于在我将工作版本提交给git之后出现的任何人!谢谢-老实说,如果我首先创建MCVE,我会走得更快-今晚我花了2个小时来制作MCVE并在原始项目中解决问题;在今晚之前,我浪费了三天时间试图解决这个问题。它只是去表明一点点努力真的有回报!请你改变我的构造器上面,并张贴完成的构造器?我很难理解你的所有建议:我已经取消了回调,我得到了相同的错误是的,因为在返回代码部分失败,在它到达回调之前。太好了!考试通过了!谢谢你的帮助!对于在我将工作版本提交给git之后出现的任何人!谢谢-老实说,如果我首先创建MCVE,我会走得更快-今晚我花了2个小时来制作MCVE并在原始项目中解决问题;在今晚之前,我浪费了三天时间试图解决这个问题。它只是去表明一点点努力真的有回报!