2016-06-13 9 views
0

特定のテストのために私のコントローラを駆動するためにテストハーネス(SpecFlow 2.0.0 over NUnit 3.0.5797.27534)をリファクタリングする途中です。IHttpControllerActivatorでDo-Not-Caockを嘲笑

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コールをモックしようとしている...

[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はthuslyなります

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; 

} 

私の最初の傾きがTimeControllerが原因Createの署名のモックや経路に対する私の実行が要求を提供していないという事実によって返されていないことを考えるようにしましたアクティベーターのセットアップで提供されたモックと一致する記述子が含まれています。

だから、私はディスパッチャの作成をスワップ: (リクエストとcontrollerDescriptorはIsAnyチェックに置き換え) dispatcher.Setup(コンテキスト=> context.Create(It.IsAny()、It.IsAny()、controllerType )))戻り値(サービス);

しかし、私の要求は、定義されたルートをヒットしません。

client.GetAsyncへの呼び出しで、私のモックTimeControllerを戻す方法を知っている人は誰ですか?

+0

おっと!私は古い試みからの 'dispatcher.Setup'コードを含んでいたので、おそらく全体的に意味をなさないでしょう。この質問の理由は、私のdispatcher.Setup(context => context.Create ...)コードでは、 'request.Object'は実際には' Moq.It.IsAny 'であり、' descriptor.Object'は実際には'Moq.It.IsAny 'と表示され、依然としてリクエストを取得できません。 –

答えて

0

Moqは問題ではありませんでした。私のStartupの中には、IAppBulder.Map('NewRoute',...)の背後に設定された属性ルートが誤って隠されていました.1そのナンセンスを修正した後、上記のコードは必要に応じて機能します。誰かが、研究では、この全体につまずく場合には完全期すために、私はテストに合格するために得るために、私のクライアントコードを変更する必要がありました:

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 

..itは(「アプリケーションを除いて、元のコードと同じです/ 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. 
関連する問題