Asp.net mvc 3 单元测试MVC控制器,使用UnityAutoMoq解析采用构造函数参数的接口

Asp.net mvc 3 单元测试MVC控制器,使用UnityAutoMoq解析采用构造函数参数的接口,asp.net-mvc-3,unit-testing,unity-container,automocking,Asp.net Mvc 3,Unit Testing,Unity Container,Automocking,正如标题所说,我正在尝试解析一个接口,该接口实现了一个也采用构造函数的具体类 以下是具体服务类的示例: public class MessageService : IMessageService { private readonly IMessageGenerator _messageGenerator; public MessageService(IMessageGenerator messageGenerator) { _messageGenerat

正如标题所说,我正在尝试解析一个接口,该接口实现了一个也采用构造函数的具体类

以下是具体服务类的示例:

public class MessageService : IMessageService
{
    private readonly IMessageGenerator _messageGenerator;

    public MessageService(IMessageGenerator messageGenerator)
    {
        _messageGenerator = messageGenerator;
    }

    public string GetMessage()
    {
        return string.Concat(_messageGenerator.GetMessage(), "");
    }
}
正如您所看到的,这个服务类还需要一个接口作为构造函数参数。MVC控制器构造函数如下所示:

    private readonly IMessageService _messageSvc;

    public HomeController(IMessageService messageSvc)
    {
        _messageSvc = messageSvc;
    }
由于Unity.Mvc3,我已经解决了引导程序中的接口问题

var container = new UnityContainer();

container
        .RegisterType<IMessageService, MessageService>()
        .RegisterType<IMessageGenerator, MessageGenerator>();
var container=newunitycontainer();
容器
.RegisterType()
.RegisterType();
因此,我面临的主要问题是如何在使用UnityAutoMoq的单元测试中,将IMessageGenerator接口的模拟实例传递给IMessageService?我想这样的事情会管用,但事实并非如此:

    [TestMethod]
    public void Index()
    {
        var container = new UnityAutoMoqContainer();
        var controllerContext = container.Resolve<ControllerContext>();
        var nMsgSvc = container.Resolve<IMessageService>(container.Resolve<IMessageGenerator>);
        var sut = new HomeController(nMsgSvc) { ControllerContext = controllerContext };

        ViewResult result = sut.Index() as ViewResult;

        Assert.AreEqual("Hello from the MessageGenerator via the MessageService", result.ViewBag.Message);
    }
[TestMethod]
公共空间索引()
{
var container=new UnityAutoMoqContainer();
var controllerContext=container.Resolve();
var nMsgSvc=container.Resolve(container.Resolve);
var sut=newhomecontroller(nMsgSvc){ControllerContext=ControllerContext};
ViewResult=sut.Index()作为ViewResult;
AreEqual(“通过MessageService来自MessageGenerator的Hello”,result.ViewBag.Message);
}

测试控制器时不需要这样做。在这种情况下,控制器只需要IMessageService的模拟

此外,为了测试Index方法,我根本不会使用容器,因为它不涉及

像这样的东西应该可以做到:

// arrange
var messageService = new Mock<IMessageService>();
// setup message service
...

var controller = new HomeController(messageService.Object);

// act
...
//排列
var messageService=new Mock();
//设置消息服务
...
var controller=新的HomeController(messageService.Object);
//表演
...

测试控制器时不需要这样做。在这种情况下,控制器只需要IMessageService的模拟

此外,为了测试Index方法,我根本不会使用容器,因为它不涉及

像这样的东西应该可以做到:

// arrange
var messageService = new Mock<IMessageService>();
// setup message service
...

var controller = new HomeController(messageService.Object);

// act
...
//排列
var messageService=new Mock();
//设置消息服务
...
var controller=新的HomeController(messageService.Object);
//表演
...

这个问题很久以前就被问到了。但我会提供一个可能有用的答案。你真的不想存根IMessageGenerator。您想要的是删除IMessageService。并将其配置为返回所需的消息。IMessageGenerator返回的内容与控制器无关。只有在控制器中使用IMessageGenerator时才会引起关注

注意,您的测试在使用UnityAutoMoq容器时也写得不好

您可以将IMessageService配置为返回所需字符串,如下所示

    [TestMethod]
    public void Index_ViewData_ContainsExpectedMessage()
    {
        var container = new UnityAutoMoqContainer();
        var messageToReturnViaMessageGenerator = "Hello from the MessageGenerator via the MessageService";                        
        var messageGenratorStub = container.GetMock<IMessageService>();
        messageGenratorStub.Setup(x => x.GetMessage()).Returns(messageToReturnViaMessageGenerator);
        var sut = container.Resolve<HomeController>();

        ViewResult result = sut.Index() as ViewResult;

        Assert.AreEqual(messageToReturnViaMessageGenerator, result.ViewBag.Message);
    }
[TestMethod]
public void Index_ViewData_ContainsExpectedMessage()
{
var container=new UnityAutoMoqContainer();
var messagetoreturnvia MessageGenerator=“通过MessageService从MessageGenerator发送Hello”;
var messageGenratorStub=container.GetMock();
messageGenratorStub.Setup(x=>x.GetMessage()).Returns(messageToReturnViaMessageGenerator);
var sut=container.Resolve();
ViewResult=sut.Index()作为ViewResult;
Assert.AreEqual(messageToReturnViaMessageGenerator,result.ViewBag.Message);
}
没有什么值得注意的

  • 您不需要解析ControllerContext-在本测试中不需要解析
  • 解决Sut

        var sut = container.Resolve<HomeController>();
    
    var sut=container.Resolve();
    
这将返回sut(测试中的系统)。此实例还可以包含您使用UnityAutoMoqContainer存根的任何存根实例。在本例中,它是存根的IMessageService。这样,您就不必显式地将存根IMessageService实例传递给控制器的构造函数

  • 只是一个次要的-始终提供一个可读的测试名称;)

这个问题很久以前就被问过了。但我会提供一个可能有用的答案。你真的不想存根IMessageGenerator。您想要的是删除IMessageService。并将其配置为返回所需的消息。IMessageGenerator返回的内容与控制器无关。只有在控制器中使用IMessageGenerator时才会引起关注

注意,您的测试在使用UnityAutoMoq容器时也写得不好

您可以将IMessageService配置为返回所需字符串,如下所示

    [TestMethod]
    public void Index_ViewData_ContainsExpectedMessage()
    {
        var container = new UnityAutoMoqContainer();
        var messageToReturnViaMessageGenerator = "Hello from the MessageGenerator via the MessageService";                        
        var messageGenratorStub = container.GetMock<IMessageService>();
        messageGenratorStub.Setup(x => x.GetMessage()).Returns(messageToReturnViaMessageGenerator);
        var sut = container.Resolve<HomeController>();

        ViewResult result = sut.Index() as ViewResult;

        Assert.AreEqual(messageToReturnViaMessageGenerator, result.ViewBag.Message);
    }
[TestMethod]
public void Index_ViewData_ContainsExpectedMessage()
{
var container=new UnityAutoMoqContainer();
var messagetoreturnvia MessageGenerator=“通过MessageService从MessageGenerator发送Hello”;
var messageGenratorStub=container.GetMock();
messageGenratorStub.Setup(x=>x.GetMessage()).Returns(messageToReturnViaMessageGenerator);
var sut=container.Resolve();
ViewResult=sut.Index()作为ViewResult;
Assert.AreEqual(messageToReturnViaMessageGenerator,result.ViewBag.Message);
}
没有什么值得注意的

  • 您不需要解析ControllerContext-在本测试中不需要解析
  • 解决Sut

        var sut = container.Resolve<HomeController>();
    
    var sut=container.Resolve();
    
这将返回sut(测试中的系统)。此实例还可以包含您使用UnityAutoMoqContainer存根的任何存根实例。在本例中,它是存根的IMessageService。这样,您就不必显式地将存根IMessageService实例传递给控制器的构造函数

  • 只是一个次要的-始终提供一个可读的测试名称;)

HTH

您看到了什么样的错误/失败?什么样的错误