在IHttpControllerActivator中嘲笑不关心

时间:2016-06-13 21:27:02

标签: c# asp.net-web-api moq

我正在重构我的测试工具(SpecFlow 2.0.0 over NUnit 3.0.5797.27534)来驱动我的控制器进行特定测试。

Scenario: FluxCapacitor Works
   Given I have entered '11-05-1955' into the Time Circuits
   When I get the DeLorean up to 88 mph
   Then the date on the newspaper should be '11-05-1955'

这是我为测试架构运行的常见脚手架示例。

public class TimeController: ApiController
{
    private TimeProvider TimeProvider{get;set;}
    public TimeController(TimeProvider timeProvider)
    {
       this.TimeProvider = timeProvider;
    }
}
[HttpGet]
[Route("Time;now")]
public DateTime GetCurrentTime()
{
   return TimeProvider.Current.Now; 
}

...所以,我试图嘲笑Then来做... {/ p>

[Then(@"the date on the newspaper should be '(.*)'")]
public void ThenTheDateOnTheNewspaperShouldBe(string p0)
{
   DateTime expected = DateTime.Parse(p0); 
   Startup startup = new Startup();

   Hosting.MySystemStartupOptions options = new Hosting.MySystemStartupOptions();


   //+===================================================================+
   //[KAB] This is the line that I think is of primary importance in this
   options.Dispatcher = DelegateThatReturnsMyMockControllerActivator();
   //+===================================================================+
   startup.Register = () => { return options;};

   //+===================================================================+
   //[options.Dispatcher] gets pushed down to my WebApiConfiguration that
   //executes [Services.Replace(typeof(IHttpControllerActivator),options.Dispatcher]
   //+===================================================================+
   using(WebApp.Start(url: "http://localhost:9000/", startup:startup.Configuration))
   using(var client = new System.Net.Http.HttpClient())
   using(System.Net.Http.HttpResponseMessage response = client.GetAsync(ResourceUnderTest.ToString()).Result)
   {
      if(response.StatusCode != System.Net.HttpStatusCode.OK)
      {
         Assert.Fail("you suck");
      }

      //never getting past, because I suck.
   }
}

因此,返回IHttpControllerActivator的代理人实际上称为Composer

Composer返回一个模拟。

Composer看起来如此:

Composer = () =>
{
   var request = new Moq.Mock<System.Net.Http.HttpRequestMessage>();
   var descriptor = new Moq.Mock<System.Web.Http.Controllers.HttpControllerDescriptor>();
   var dispatcher = new Moq.Mock<System.Web.Http.Dispatcher.IHttpControllerActivator>();

   Type controllerType = typeof(resources.controllers.TimeController);

   var provider = new Moq.Mock<TimeProvider>();
   provider.Setup(time => time.Now).Returns(Variable); //<=Variable is initialized in the `Given`

   TimeProvider timeProvider = provider.Object;
   Service = new resources.controllers.TimeController(timeProvider: timeProvider);


   //+======================================================================+
   //I can't figure out if there is a way to have "all calls to Create for a
   //specific controllerType, but I do not care about the request or the 
   //descriptor" returns [Service]
   dispatcher.Setup(context => context.Create(request.Object, descriptor.Object, controllerType)).Returns(Service);
   //+======================================================================+


   dispatcher.As<IDisposable>().Setup(disposable => disposable.Dispose());
   return dispatcher.Object;

}

我最初的倾向是认为由于Create签名而没有模拟返回TimeController,而且我对路由的执行没有提供与模拟匹配的请求和描述符。激活器设置中提供。

因此,我将Dispatcher的创建交换为: (请求和controllerDescriptor替换为IsAny检查)        dispatcher.Setup(context =&gt; context.Create(It.IsAny(),It.IsAny(),controllerType))。返回(服务);

但是我的要求没有达到规定的路线。

任何人都知道如何让我的模拟TimeController回到client.GetAsync的调用中?

1 个答案:

答案 0 :(得分:0)

Moq不是问题。在Startup内部,我错误地将配置的属性路由隐藏在IAppBulder.Map('NewRoute',...)后面.¹修复了这些废话后,我上面包含的代码按照需要工作。为了完整起见,如果有人在研究中遇到这种情况,我不得不更改我的客户端代码以通过测试:

using(WebApp.Start(url: "http://localhost:9000/", startup: startup.Configuration))
using(var client = new System.Net.Http.HttpClient))
{
   client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
   using(System.Net.Http.HttpResponseMessage response = client.GetAsync(ResourceUnderTest.ToString()).Result)
   {
      if(response.StatusCode != System.Net.HttpStatusCode.OK){Assert.Fail("you suck");}

      String content = response.Content.ReadAsStringAsync().Result;
      DateTime actual = Newtonsoft.Json.JsonConvert.DeserializeObject<DateTime>(token);
      Assert.AreEqual(actual, expected);
   }
}

► Passed Tests (1)
   ✔ FluxCapacitor

..它与原始代码相同,只是将(“application / json”)设置为客户端的Accept标头。

¹ ...I guess that my [start-stop],[start-stop],[start-stop] cycle to 
deal with drive-by interruptions finally got to me yesterday. Since I 
(obviously) didn't know exactly what the culprit was, I was concerned enough 
that the problem was in my Mock that I wanted to raise the question to the 
community before I left for the day. But walked away and looked at it again 
with a new day's eyes and it took about 30 seconds to find the culprit.