在使用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的抽象代码?
我花了很多时间在网上寻找建议,虽然有很多端到端的集成测试示例,但我似乎没有具体针对单元测试所做的事情。
答案 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...
}