1

ASP.NET サイト (MVC ではない) の単体テストを追加しようとしています。私がテストする必要があるメソッドの 1 つは、正確にはHttpRequest Requestオブジェクトを利用します。Request.PathVisual Studio 2008 の組み込みのテスト フレームワークを使用してテストを作成しようとしています。テストが問題のメソッドを実行するたびに、System.Web.HttpExecption: Request is not Available in this context. 利用できない理由 (実行中の Web サーバーがなく、パスが提供されていない) は理解していますが、メソッドのテストを続行するにはどうすればよいですか?

誰もがコードを見るのが好きなので、問題のコードは次のとおりです。

protected string PageName
{
    get 
    {
        return Path.GetFileName(Request.Path).Substring(0, Path.GetFileName(Request.Path).Length - 5); 
    }
}

protected Change SetupApproval(string changeDescription)
{
    Change change = Change.GetInstance();
    change.Description = changeDescription;
    change.DateOfChange = DateTime.Now;
    change.Page = PageName;
    return change;
}

テストは次のとおりです。

[TestMethod]
public void SetupApproval_SubmitChange_ValidateDescription()
{
    var page = new DerivedFromInternalAppsBasePage_ForTestingOnly();
    var messageToTest = "This is a test description";
    var change = page.SetupApproval(messageToTest);
    Assert.IsTrue(messageToTest == change.Description);
}

さらに、Microsoft のドキュメント ( http://msdn.microsoft.com/en-us/library/ms182526(v=vs.90).aspx[HostType("ASP.NET")] ) を読み、提案されている、[UrlToTest(http://localhost:port/pathToAspxPage.aspx")]、および[AspNetDevelopmentServer("C:\PathToDllAssembly", "NotSureParameter")]属性を 使用してみましたが、運がない。(ご覧のとおり、いくつかのパラメーターに何を使用すればよいかわかりません。)

最後に、Phil Haack の TestWebServer http://haacked.com/archive/2006/12/12/Using_WebServer.WebDev_For_Unit_Tests.aspxを試し 、Scott Hanselman の投稿http://www.hanselman.com/blog/NUnitUnitTestingOfASPNETPagesBaseClassesControlsAndOtherWidgetryUsingCassiniASPNETWebMatrixVisualStudioWebDeveloper.aspxを読みました 。フィルのサーバー、ExtractResourceメソッドのパラメーターに何を使用するかわかりません。

4

4 に答える 4

3

私は最近同様の問題に苦しんでいますが、本当に役に立ったのはMicrosoftResearchのMolesフレームワークです-http://research.microsoft.com/en-us/projects/moles/。これにより、HttpContext.Currentを含むBCLから何でも偽造することができます。

于 2012-05-17T14:24:35.213 に答える
2

Michael Feathersの著書「レガシー コードを効果的に使用する」で説明されている問題と非常によく似た問題があります。特に、リファクタリングは「Adapt Parameter」と呼ばれます。

コードの「問題」は、コードが HttpRequest、特に Request.Path に直接結合されていることです。したがって、全体的なアプローチは、コードを HttpRequest から分離することです。

上で提案したのと同様に、Michael Feather の本のアイデアに従ってデカップリングを行う別の方法を次に示します。これをコンパイルしようとはしていないので、タイプミスや構文エラーは許してください。

パブリック インターフェイス ParameterSource
{
    パブリック文字列パス {get; }
}

public class FakeParameterSource : ParameterSource
{
   公開文字列値。
   public string Path { get { return Value } }
}

public class RealParameterSource : ParameterSource
{
   プライベート HttpRequest リクエスト。
   public RealParameterSource(HttpRequest aRequest)
   {
     リクエスト = aRequest;
   }
   public string Path { get { return request.Path } }
}

ここで、変更する必要がある重要な部分を示します (変更する方法の 1 つを次に示します)。

// 小さいリネーム
保護された文字列 GetPageName(ParameterSource ソース)
{
   Return Path.GetFileName(source.Path).Substring(0, Path.GetFileName(source.Path).Length - 5);
}

上記のインジェクションはメソッド レベルで発生します。コンストラクターまたはプロパティを介して行うこともできます。

テスト コードは次のようになります。

protected Change SetupApproval(string changeDescription)
{
    ParameterSource p = 新しい FakeParameterSource { 値 = "mypath" };
    変更変更 = Change.GetInstance();
    change.Description = changeDescription;
    change.DateOfChange = DateTime.Now;
    change.Page = GetPageName(p); // パラメータ ソースの値を使用するようになりました
    変更を返します。
}

アイデアが得られ、これが役立つことを願っています

于 2012-05-22T18:47:53.870 に答える
0

@Alex Taylorに同意します(申し訳ありませんが、コメントできません):(非MVC)Webアプリの単体テストの最良の方法は、ビットが存在する環境全体に依存しないことを確認することです。結局のところ、それがユニットテストと呼ばれる理由です。したがって、これに置き換えることができますPageName

protected string PageName
{
    get 
    {
        return GetPageName(Request.Path);
    }
}

protected static string GetPageName(string path)
{
    return Path.GetFileNameWithoutExtension(path);
}

これにより、単体テストが可能GetPageNameになり、PageNameが期待どおりに機能することを確信できます。

ユニットテストを試みても意味がないことを忘れないでください。ユニットテストRequest.Pathには、実行する必要のある期待される動作(または「コントラクト」)があるためです。さまざまな状況でRequest.Pathがどのように返されるかわからない場合は、単体テストを追加するのではなく、ドキュメントを確認する必要があります。

于 2012-05-22T09:22:36.490 に答える
0

HttpContext を使用するメソッドをテストするための鍵は、HttpContextBase を使用することです。HttpContextBase は、簡単にモックできる抽象クラスです。残念ながら、HttpContext は HttpContextBase を実装していないため、HttpContextWrapper を使用して実際の HttpContext を HttpContextBase にラップする必要があります。この記事には、適切で簡単な説明があります: http://splinter.com.au/httpcontext-vs-httpcontextbase-vs-httpcontext

あなたの質問は、サンプルコードがどこにあるかを述べていません。すべてがコード ビハインドにある場合、それをテストするのは困難です。コード ビハインドにロジックを含める代わりに、Model-View-Presenter(MVP) -pattern を調べる必要があります。MVP にはフレームワークがありますが、自分で行うのも非常に簡単です。

MVP プレゼンターでは、すべてのロジックとページの分離コードが含まれ、UI にバインドできるプロパティを含むビュー インターフェイスのみが実装されます。すべての依存関係をプレゼンターに注入して、テストを容易にすることができます。

于 2012-05-21T04:47:40.370 に答える