2013-01-16 62 views
1

我在研究NSpec框架。在外部環境中重用NSpec規範

這是我的例子。我寫規範一個簡單的HttpRequester類:

using Moq; 
using NSpec; 

namespace FooBrowser.UnitTests.BDD 
{ 
    class HttpRequester_specification : nspec 
    { 
     private HttpRequester requester; 

     private string sentData; 
     private int sendTimes; 

     private readonly Mock<IConnection> connectionMock; 
     private string resource; 

     public HttpRequester_specification() 
     { 
      connectionMock = new Mock<IConnection>(); 

      connectionMock 
       .Setup(x => x.Send(It.IsAny<string>())) 
       .Callback<string>(data => 
       { 
        sendTimes++; 
        sentData = data; 
       }); 
     } 

     void given_opened_connection_with_no_recent_sends() 
     { 
      before =() => 
      { 
       sendTimes = 0; 
      }; 

      context["when HttpRequester is constructed"] =() => 
      { 
       before =() => requester = new HttpRequester(connectionMock.Object); 

       it["should not do any request"] =() => sendTimes.should_be(0); 

       context["when performing request"] =() => 
       { 
        act =() => requester.Request(resource); 

        context["when resource is not specified"] =() => 
        { 
         it["should do 1 request"] =() => sendTimes.should_be(1); 
         it["should send HTTP GET/HTTP/1.0"] =() => sentData.should_be("GET/HTTP/1.0"); 
        }; 

        context["when resource is index.html"] =() => 
        { 
         before =() => resource = "index.html"; 

         it["should do 1 request"] =() => sendTimes.should_be(1); 
         it["should send HTTP GET /index.html HTTP/1.0"] =() => sentData.should_be("GET /index.html HTTP/1.0"); 
        }; 
       }; 
      }; 
     } 
    } 
} 

正如你可以看到它[ 「應該做1個請求」] =()=> sendTimes.should_be(1);被寫兩次。

我嘗試將其移動到外上下文這樣的:

context["when performing request"] =() => 
{ 
    act =() => requester.Request(resource); 

    context["when resource is not specified"] =() => 
    { 
     it["should send HTTP GET/HTTP/1.0"] =() => sentData.should_be("GET/HTTP/1.0"); 
    }; 

    context["when resource is index.html"] =() => 
    { 
     before =() => resource = "index.html"; 

     it["should send HTTP GET /index.html HTTP/1.0"] =() => sentData.should_be("GET /index.html HTTP/1.0"); 
    }; 

    it["should do 1 request"] =() => sendTimes.should_be(1); 
}; 

但是這會導致它[ 「應該做1個請求」] =()=> sendTimes.should_be(1);檢查一次外部上下文,而不是內部的,因爲我想要的。

那麼,我可以以某種方式將它移動到外部環境嗎?

或者更容易向NSpec貢獻一些代碼來啓用此類行爲?

我發現類似的問題在這裏Reusing NSpec specifications,但我想保持拉姆達表達式語法(沒有繼承),看看在1處所有規格。

回答

2

對不起看到這是沒有答案了兩個星期,但我解決它只是通過提取方法像

void ItShouldRequestExactly(int n) 
{ 
    it["should do " + n + " request"] =() => sendTimes.should_be(n); 
} 

這是足夠乾燥,我在大多數情況下。 當你在它們在規範執行時間其實初始化對象通過你得到然而微妙的問題,但是對於這個簡單的例子,它非常適合。 我很遺憾沒有看到另一種方式將這種混入聲明注入上下文中。