2012-02-01 6 views
2

AccountController.LogInメソッドをチェックするユニットテストがあります。成功を示すためにリダイレクト結果が返されます。そうでない場合は、viewresultが返されます。ユニットテストカスタムMembershipProvider.ValidateUser、Global.asaxのコードを使用

資格情報が有効なのでテストが成功を返す必要があるにもかかわらず、戻り値の型は常にviewresultであるため、テストは常に失敗しますが、どこに問題があるか特定できません。 私のtestMethod: CustomerRepositoryTest.cs

[TestMethod] 
public void Can_Login_With_Valid_Credentials() 
{ 
    // Arrange 
    Mock<IAddressRepository> mockAddressRepository = new Mock<IAddressRepository>(); 
    Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>(); 
    Mock<IOrderRepository> mockOrderRepository = new Mock<IOrderRepository>(); 

    LoginViewModel model = new LoginViewModel 
    { 
     Email = "[email protected]", 
     Password = "password" 
    }; 

    AccountController target = new AccountController(mockCustomerRepository.Object, mockAddressRepository.Object, mockOrderRepository.Object); 

    // Act 
    ActionResult result = target.LogIn(model); 

    // Assert 
    Assert.IsInstanceOfType(result, typeof(RedirectResult)); 
    Assert.AreEqual("", ((RedirectResult)result).Url); 
    } 

私がテストを実行すると、私は私のカスタムのMembershipProvider AccountController.cs

if (Membership.ValidateUser(LoginModel.Email, LoginModel.Password)) 
{ 
    ... 
return RedirectToRoute(new 
{ 
    controller = "Account", 
    action = "Details" 
}); 
} 
else 
{ 
    return View(); 
} 

のvalidateUser 呼ぶとき、それは私のAccountControllerログイン方法に失敗しましたValidateUserは次のようになります。

AccountMembershipProvider.cs

public class AccountMembershipProvider : MembershipProvider 
{ 
    [Inject] 
    public ICustomerRepository repository { get; set; } 

    public override bool ValidateUser(string username, string password) 
    { 
     var cust = repository.GetAllCustomers().SingleOrDefault.. 

私がテストしていない通常、すなわちアプリケーションを実行して、ログインが正常に動作します。アプリケーションでは、私は、Global.asaxのでカスタムメンバシッププロバイダにCustomerRepositoryを注入:

public class MvcApplication : System.Web.HttpApplication 
    { 
     private IKernel _kernel = new StandardKernel(new MyNinjectModules()); 

     internal class MyNinjectModules : NinjectModule 
     { 
     public override void Load() 
     { 
      Bind<ICustomerRepository>().To<CustomerRepository>(); 
     } 
     } 

     protected void Application_Start() 

    { 
    _kernel.Inject(Membership.Provider); 
    ... 

Global.asaxのコードは、ユニットテスト中に実行されていない場合ですか?私のカスタムプロバイダは注入されていないので、失敗しますか?

UPDATE 私は私のプロバイダクラスを嘲笑し、それに嘲笑CustomerRepositoryオブジェクトを通過しました。

mockCustomerRepository.Setup(m => m.IsValidLogin("[email protected]", "password")).Returns(true); 

しかし残念ながら、私はまだたびに失敗取得しています:

Mock<AccountMembershipProvider> provider = new Mock<AccountMembershipProvider>(); 

provider.Object.repository = mockCustomerRepository.Object; 

は、私は、私がテストしようとしている方法のためのセットアップを作成しました。テストのために実際のオブジェクトや嘲笑されたオブジェクトが必要かどうかについての質問に答えるために - 私は気難しいことではない、私はちょうどその時働いてほしい! 2

UPDATE私はそれらの変更を行い、それがまだ失敗している間、それは私が特定の問題を識別することができました。テストをデバッグしている間、私は私が呼ぶときMembership.Providerは(おそらくデフォルトのタイプである)、その結果、検証が失敗したタイプのSqlMembershipProviderである

Membership.ValidateUser(LoginModel.Email, LoginModel.Password) 

上書きすることを発見しました。

私は...私のカスタムプロバイダに

((AccountMembershipProvider)Membership.Provider).ValidateUser(LoginModel.Email, LoginModel.Password) 

をプロバイダをキャストした場合、テストを実行しているとき、私はInvalidCastExceptionが得られます。だから私の模倣AccountMembershipProviderは、テストに使用されていない代わりに、デフォルトのプロバイダが使用されているようです。

私はすでにコメントでこれを発見したと思う:私はあなたが正確に何を意味するかわからないんだけど、しかし

// set your mock provider in your AccountController 

- 私は、プロバイダを割り当てるために、私のAccountControllerのプロパティを持っていない、と私はそれをコンストラクタに注入していません。

+0

私はちょうどあなたに知らせるために、私はその日の早い段階で私の答えにさらに編集した情報を加えました。明確化またはより具体的な情報を求めることをためらってください。 – Gilles

+0

@ Gilles - 私はあなたの提案を実装しました(更新を参照)。彼らは私のために多くのことを明確にしましたが、残念ながら毎回失敗しています! ProviderクラスとRepositoryクラスの両方の設定メソッドを定義する必要がありますか? – markpsmith

+0

私のポストを例文で更新します。基本的にあなたのプロバイダが虚偽の場合、モックオブジェクトがそれらを呼び出さないため、依存関係のためのモックを作成する必要はありません。 – Gilles

答えて

3

あなたの元の質問: 「それはGlobal.asaxのコードはユニットテスト中に実行されていないので、私のカスタムプロバイダが注入されていない、ので、失敗している場合か?」

私の答え:

はい。

global.asaxファイルは、実行時にASP.NetとISSによって使用されます。サーバーが最初の要求を受け取るとコンパイルされます。

テストするときは、ISSで実行されているASP.Net Webアプリケーションのコンテキストではなく、テストセッションで実行されているプログラムで実行されます。つまり、global.asaxは呼び出されません。

はさらに重要なのは、あなたが呼び出すとき:

Mock<ICustomerRepository> mockCustomerRepository = new Mock<ICustomerRepository>(); 

をNinjectフィル輸入呼び出されません。 Moqはインタフェースに基づいてモックを作成します。実際のオブジェクトは作成されません。

あなたはすなわち、任意のセットアップ方法を定義していませんでしたので:

mockCustomerRepository.Setup(mock => mock.MyAuthenticateMethod()).Returns(true); 

あなたがいない定義された動作でモックの周りに渡しています。 デフォルトでは、これらはfalseを返します。これはおそらくあなたが常に視点の結果を得ている理由を説明します。

あなたがしなければならないことは、模擬する必要のあるメソッドの設定メソッドを定義することです。

target.LogIn(model); 

またNInjectが使用されることはありませんので、ごAccountMembershipProviderはCustomerRepositoryがそれを注入しています得ることはありませんのでご注意:

これらの呼び出しがときに呼び出されますCustomerRepositoryの方法ですAccountControllerをテストしていて静的でない場合(Moqは静的では機能しません)、AccountMembershipProviderを嘲笑することを検討する必要があります。できない場合は、テストでCustomerRepositoryの虚偽のインスタンスをAccountMembershipProvider.repositoryに提供する必要があります。

また、Moqモックを作成する代わりに、テストでCustomerRepositoryの実際のインスタンスを手動で(新規に)作成することもできます。

あなたはNinjectにそれをさせることができますが、この時点ではなぜですか?自分で作成することができ、作成する特定のタイプを知ることができます。

このテストでは、モックまたはオブジェクトの実際のインスタンスが必要な場合は、すべて終了します。

更新:

プロバイダが嘲笑されている場合は、その上のリポジトリを設定する必要はありません。モックを呼び出すと、実際のオブジェクトは呼び出されません。

Mock<AccountMembershipProvider> provider = new Mock<AccountMembershipProvider>(); 
// set your mock provider in your AccountController 

provider.Setup(m => m.ValidateUser("[email protected]", "password")).Returns(true); 

アップデート2:私はあなたのテスト作業を行うことにかなり近いと思います

あなたがする必要がどのような

はこのようなものです。あなたのコード(テストとテスト中のクラス)のすべてを見ることなく、私は本当にあなたにもう助けてもらえません。私はあなたの元の質問に答えたと感じますが、まだ立ち往生している場合、あなたが現在取り組んでいる問題に関する新しい質問をすることによって、より多くの助けを得るかもしれません。

+0

私の最後の編集で、私は答えにいくつかの情報を追加しました。新しい部分はイタリック体です。 – Gilles

+0

私は、私のオリジナルの質問が本当に答えられたと感じています。あなたが単に答えを出すことを超えたという事実はあなたの信用です。 – markpsmith

+0

@Gilles、あなたは "//あなたのAccountControllerであなたの擬似プロバイダを設定する"と言いました。あなたは、プロバイダをコントローラに設定する方法の例を教えてください –

1

コードでは、コントローラを作成するだけですが、メンバーシップの初期化は実行しません。 ValidateUserメソッドを持つ独自のUserServiceを作成し、静的クラスメンバーシップの代わりに必要なものを作成することをお勧めします。

関連する問題