1

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); 2回書かれています。

私はそれを次のように外側のコンテキストに移動しようとします:

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);
};

しかし、これは ["should do 1 request"] = () => sendTimes.should_be(1); になります。私が望むように、内側のコンテキストではなく、外側のコンテキストに対して一度チェックされます。

それで、どういうわけかそれを外側のコンテキストに移動できますか?

それとも、そのような動作を可能にするコードを NSpec に提供する方が簡単ですか?

ここで同様の質問を見つけましたReusing NSpec specificationですが、すべての仕様を 1 か所で確認するためにラムダ式の構文 (継承なし) を維持したいと考えています。

4

1 に答える 1

2

申し訳ありませんが、これは2週間回答されていませんが、次のようなメソッドを抽出するだけで回避できます。

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

ほとんどの場合、これは私にとって十分に乾燥しています。ただし、スペックの実行時に実際に初期化されるオブジェクトを渡すと、微妙な問題が発生しますが、この単純な例では完全に適合します。悲しいことに、そのようなミックスインアサーションをコンテキストに挿入する別の方法はわかりません。

于 2013-01-31T10:14:07.887 に答える