如何对使用ServiceStack的JsonServiceClient()的ASP.NET MVC操作进行单元测试?

时间:2013-08-04 14:00:45

标签: c# asp.net-mvc nunit servicestack

在使用ASP.NET MVC时,我对可测试设计有相当深刻的理解,并且成功地将这种理解应用于使用ServiceStack构建可测试服务。但是,一个非常重要的难题包括我,我如何单元测试依赖于JsonServiceClient的MVC操作?我知道我可以将JsonServiceClient包装在我自己的抽象中,但是有没有基于ServiceStack的解决方案?

例如,提供一个使用DTO获取行星列表的人为服务:

public class PlanetsService : Service
{
    public IRepository Repository { get; set; } // injected via Funq

    public object Get(PlanetsRequest request)
    {
        var planets = Repository.GetPlanets();

        return new PlanetsResponse{ Planets = planets };
    }
}

假设我有一个简单的MVC动作,它使用JsonServiceClient来获取数据,做一些工作,然后返回一个包含我的行星列表的视图模型的视图:

public class PlanetsController : Controller
{
    private readonly IRestClient _restClient; // injected with JsonServiceClient in AppHost

    public PlanetsController(IRestClient restClient)
    {
        _restClient = restClient;
    }

    public ActionResult Index()
    {
        var request = new PlanetsRequest();
        var response = _restClient.Get(request);

        // maybe do some work here that we want to test

        return View(response.Planets);
    }
}

我开始在我的单元测试中使用DirectServiceClient作为我的IRestClient但是没有实现DirectServiceClient.Get(IRequest请求)(抛出NotImplementedException)。我的测试使用的是NUnit,并继承自ServiceStack的TestBase:

[TestFixture]
public class PlanetsControllerTests : TestBase
{
    [Test]
    public void Index_Get_ReturnsViewResult()
    {
        var restClient = new DirectServiceClient(this, new ServiceManager(typeof(PlanetsService).Assembly));
        var controller = new PlanetsController(restClient);
        var viewResult =  controller.Index() as ViewResult;

        Assert.IsNotNull(viewResult);
    }

    protected override void Configure(Funq.Container container)
    {
        // ...
    }
}

所以我猜真正的问题是:DirectServiceClient是否可以为IRestClient提供单元测试?对于使用带有ASP.NET MVC的ServiceStack的开发人员,ServiceStack是否为我所假设的策略提供了策略?我是否在ServiceStack产品范围之外工作,或许我应该编写自己隐藏JsonServiceClient的抽象代码?

我花了很多时间在网上寻找建议,虽然有很多端到端的集成测试示例,但我似乎没有具体针对单元测试所做的事情。

1 个答案:

答案 0 :(得分:0)

你不能只创建自己的IRestClient模拟实现吗?或者更好地使用像RhinoMock这样的东西来模拟界面并设置期望和响应?

例如,使用RhinoMock(不确定真正的语法,但应该清楚发生了什么):

[Test]
public void Index_Get_ReturnsViewResult()
{
    var restClient = MockRepository.GetMock<IRestClient>();
    var controller = new PlanetsController(restClient);
    restClient.Expect(c => c.Get(null)).IgnoreArguments().Return(new PlanetsResponse{ /* some fake Planets */ });
    var viewResult =  controller.Index() as ViewResult;

    Assert.IsNotNull(viewResult);
    // here you can also assert that the Model has the list of Planets you injected...
}