2

私は単体テストを学ぼうとしています。asp.net mvc 1.0で作成しているメンバーシップの一部を単体テストしようとしています。私は MVC に関する本を読んでいて、うまくいけば誰かが私のために片付けてくれるものについて混乱しています。

フレームワークに Nunit と Moq を使用しています。

質問1:

  public AuthenticationController(IFormsAuthentication formsAuth, MembershipProvider provider)
        {
            FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
            Provider = provider ?? Membership.Provider;
        }

私はちょっと混乱しています「??」私は本当に前にそれを見たことがありませんか。ここで実際に何が起こっているのかさえわからないように。インターフェイスを渡してから「??」を渡すように マークが発生し、新しい FormsAuthenticationWraper が作成されますか?

質問2。

 public AuthenticationController(): this(null, null)
        {
        }

これがデフォルトのコンストラクターであることは知っていますが、「: this(null,null)」が実行されている理由がわかりません。

それは何を実装していますか?そして、これも何を参照していますか。それに加えて、なぜそれを除外できないのでしょうか。そして、デフォルトのコンストラクターをそのまま貼り付けます。

質問3。

本 (asp.net mvc 1.0 をすばやく) では、Memembership プロバイダーを実装するのにかなりの作業が必要になることについて説明しています。そのため、彼らは moq モックアップ フレームワークを使用して生活を楽にしています。

今私の質問は、彼らが「FormsAuthentication」でmoqを使用していないということです。代わりにインターフェースを作成します

   public interface IFormsAuthentication
        {
            void SetAuthCookie(string userName, bool createPersistentCookie);
            void SignOut();


        }

次に、ラッパーを作成します

public class FormsAuthenticationWrapper : IFormsAuthentication { public void SetAuthCookie(string userName, bool createPersistentCookie) { FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); } public void SignOut() { FormsAuthentication.SignOut(); }

}

そして最後にプロパティ

   public IFormsAuthentication FormsAuth
        {
            get;
            private set;
        }

メンバーシップと同様に、彼らだけが持っています

public static MembershipProvider プロバイダー { get; プライベートセット; }

何を変更するのかもわかりません。この行も何に変更しますか?

フォーム認証 = フォーム認証 ?? 新しい FormsAuthenticationWrapper();

また、FormsAuthentication インターフェイスとラッパーに別のメソッドを追加しようとしました。

public void RedirectFromLoginPage(string userName, bool createPersistentCookie) { FormsAuthentication.RedirectFromLoginPage(userName, createPersistentCookie); }

それでも、何が起こっているのかわかりませんが、ユニットテストは常に失敗します。それを修正するために何をしようとしても関係ありません。

     public ActionResult Login(string returnUrl, FormCollection form, bool rememberMe)
            {
                LoginValidation loginValidation = new LoginValidation();
                try
                {
                    UpdateModel(loginValidation, form.ToValueProvider());

                }
                catch
                {

                    return View("Login");
                }

                if (ModelState.IsValid == true)
                {

                    bool valid = authenticate.VerifyUser(loginValidation.UserName, loginValidation.Password);

                    if (valid == false)
                    {
                        ModelState.AddModelError("frm_Login", "Either the Password or UserName is invalid");

                    }
                    else if (string.IsNullOrEmpty(returnUrl) == false)
                    {
                        /* if the user has been sent away from a page that requires them to login and they do 
                         * login then redirect them back to this area*/
                        return Redirect(returnUrl);
                    }
                    else
                    {

                       FormsAuth.RedirectFromLoginPage(loginValidation.UserName, rememberMe);
                    }

                }


                return View("Login");


Here is my test

[テスト] public void Test_If_User_Is_Redirected_Back_To_Page_They_Came_From_After_Login() { System.Diagnostics.Debugger.Break();

       var formsAuthenticationMock =  new Mock<AuthenticationController.IFormsAuthentication>();

       var membershipMock = new Mock<MembershipProvider>();

       membershipMock.Setup(m => m.ValidateUser("chobo2", "1234567")).Returns(true);


       // Setup controller
       AuthenticationController target = new AuthenticationController(formsAuthenticationMock.Object, membershipMock.Object);


       // Execute
       FormCollection form = new FormCollection();
       form.Add("Username", "chobo2");
       form.Add("password", "1234567");

       ViewResult actual = target.Login(null, form, false) as ViewResult;

       Assert.That(actual.View, Is.EqualTo("home"));
       formsAuthenticationMock.Verify();

   }

実際は常に null に戻ります。ViewResult、RedirectResult、RedirectToRouteResult を試しましたが、全員が null に戻ります。最初に奇妙だと思うので、なぜこれが起こっているのかわかりません

                       FormsAuth.RedirectFromLoginPage(loginValidation.UserName, rememberMe);

ビューを停止せず、リダイレクトを開始します。最初は、この行に到達すると return ステートメントのようなもので、他のコードは実行されないと思いましたが、そうではないように見えるので、これが問題になるかどうかはわかりません。

ありがとう

4

7 に答える 7

11

質問1

これはnull 合体演算子??と呼ばれ、C# 2.0 以降の非常に便利な機能です。

あなたの場合、

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

単に「 null でない限り割り当てformsAuthFormsAuthnull の場合は割り当てnew FormsAuthenticationWrapper()」を意味します。これは基本的に、コード内の null 参照を防ぐ方法です。次の条件式のショートカットと考えることもできます。

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

質問2

の使用は、コンストラクター チェーンthis(null, null)と呼ばれます。これが意味することは、コンストラクターの本体が実行される前に、2 つのパラメーターを受け取る同じクラス (したがって、親クラスとは対照的に) 内のコンストラクターを呼び出す必要があるということです。thisbase

コンストラクターのオーバーロードは、開発者がデフォルトのプロパティ/設定を使用したい場合に新しいオブジェクトを簡単に作成できるようにするための一般的な方法です。

質問 3

他の人が述べたように、これは実際には別の質問として属します。前の 2 つとは異なり、C# の言語機能ではなく、コンテキスト/コードに固有のものです。

アップデート

わかりました、私が今行ったことは実際にここで 2 つのコンストラクターを書き直したものです。なぜなら、それらを別の (実質的に同等の) 形式に置く方が少し明確であり、おそらくより良い設計方法でもあると思うからです。ここでは null 合体演算子は必要ありません。

public AuthenticationController()
    : this(new FormsAuthenticationWrapper(), Membership.Provider)
{
}

public AuthenticationController(IFormsAuthentication formsAuth,
    MembershipProvider provider)
{
    this.FormsAuth = formsAuth;
    this.Provider = provider;
}

この形式では、2 つのパラメーターを受け取るコンストラクターがクラス変数を引数の値に割り当てるだけであることは明らかです。パラメーターなしのコンストラクター (多くの場合、既定のコンストラクターと呼ばれます) は、コンストラクターの連鎖によって指定された既定 FormsAuthのオブジェクトとオブジェクトを使用して、新しいオブジェクトを作成するだけです。Provider

于 2009-06-22T12:58:29.993 に答える
1

質問1: ??null 合体演算子です。?? 演算子は、式の左側に指定された値が null であるかどうかをチェックし、そうである場合は、式の右側で示される代替値を返します。

あなたの状況では、null かどうかをチェックし、formsAuthnull の場合は新しい FormsAuthenticationWrapper() を返します。

于 2009-06-22T12:57:06.627 に答える
1

?? 演算子は、「nullでない限り、これを使用してください。その場合は、この他のものを使用してください」と言っています。

したがって、このコード行:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

以下と同じです:

if ( formsAuth != null ) FormsAuth = formsAuth
else FormsAuth = new FormsAuthenticationWrapper();
于 2009-06-22T12:57:55.783 に答える
0

質問2

public AuthenticationController(): this(null, null)
{
}

AuthenticationControllerのnoパラメーターコンストラクターは、IFormsAuthenticationとMembershipProviderを受け取るコンストラクターを呼び出し、2つのnull値を渡します(これは、no-paramコンストラクターコードブロック内のコードが実行される前に実行されます)。2つの引数のコンストラクターはnull合体(??)演算子を使用して変数を割り当て、渡された引数はnullであるため、Membership.Providerオブジェクトとともに新しいMembershipProviderが使用されます。

このコンストラクターが明示的に定義されていなかった場合、デフォルトのパラメーターなしコンストラクターが使用されます。これにより、新しいAuthenticationControllerが(コンストラクターに引数を渡さずに)作成された場合、メンバー変数が初期化されなかったため、予期しない動作が発生する可能性があります。

于 2009-06-22T13:19:47.987 に答える
0

Q2の答えとして

コンストラクターをオーバーロードしています。

If は呼び出しを意味します

Foo() 

呼び出しと同じです

Foo(null, null)
于 2009-06-22T13:00:10.693 に答える
0

質問1:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
Provider = provider ?? Membership.Provider;

に等しい:

FormsAuth = (formsAuth == null ? new FormsAuthenticationWrapper() : formsAuth);
Provider = (provider == null ? Membership.Provider : provider);

質問2:

formsAuth とプロバイダーのコンストラクター引数の両方に null を渡すだけです。それは良い習慣ではありません。引数のない別のコンストラクターの方が適しています。

編集:これは意味がありません。申し訳ありませんが、私は急いでいたので、コンストラクターが別のコンストラクターを呼び出していることに気付きませんでした。

今は質問 3 に答える時間がありません。それについては後で説明します...

于 2009-06-22T13:01:36.277 に答える
0

質問 1:オペレーターは単に 「??null でない場合は左にあるものをすべて取得し、null の場合は右にあるものをすべて取得します」と言うだけです。だからあなたのコード:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

と同等です

if (formsAuth != null) {
    FormsAuth = formsAuth;
} else {
    FormsAuth 0 new FormsAuthenticationWrapper();
}

質問 2::this(null, null)構文は「コンストラクターの継承」の省略形です (私の命名...) 。あなたのコード

public AuthenticationController(): this(null, null)
    {
    }
public AuthenticationController(IFormsAuthentication formsAuth, MembershipProvider  provider)
    {
        FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();
        Provider = provider ?? Membership.Provider;
    }

と同等です

public AuthenticationController()
    {
        FormsAuth = new FormsAuthenticationWrapper();
        Provider = Membership.Provider;
    }
public AuthenticationController(IFormsAuthentication formsAuth, MembershipProvider provider)
    {
        FormsAuth = formsAuth;
        Provider = provider;
    }
于 2009-06-22T13:01:58.130 に答える