2

在使用 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 request) 没有实现(抛出 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 进行单元测试吗?ServiceStack 是否为我假设的开发人员使用 ServiceStack 和 ASP.NET MVC 的常见场景提供了一种策略?我是否在 ServiceStack 的产品范围之外工作,也许我应该只编写隐藏 JsonServiceClient 的自己的抽象代码?

我花了很多时间在网上寻找建议,虽然有很多端到端集成测试示例,但似乎没有一个特定于我试图用单元测试做的事情。

4

1 回答 1

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...
}
于 2013-08-04T15:43:03.917 回答