2012-02-05 6 views
8

AccountControllerをテストします。私はweb.configファイルを使用して設定CustomMembershipProviderを使用したWebアプリケーションでメンバーシップを使用するときにASP.NET MVC 3認証をテストする方法

Membership.CreateUser(model.Email, model.Password, model.Email, null, null, true, null, out createStatus); 

:問題は、Registerメソッドで、私は、ユーザーを作成するために、次の行を使用することです。私のユニットテストでは、会員資格クラスは標準SqlMembershipProviderです。私のアプリで使っている私のCustomMembershipProviderではありません。

ユニットテストコンテキストでメンバーシップを設定するにはどうすればよいですか?私はaspネットがweb.configファイルを読んだ後にそれを設定するので、プログラムで設定することを意味します。

私はすでにユーザー管理データレイヤーをモックするためにインターフェイスを使用していますが、この場合はインターフェイスを回避する方法があると思っていました。単体テストのメンバーシップの模擬実装をセットアップできるようにする。このようなあなたのMVCアプリケーションのためにそれを実装する...

public interface IMembershipProvider 
{ 
    void CreateUser(string username, string password); 
} 

public void RegisterTest() 
{ 
    IUsersManager repository = new Tests.Data.UsersManager(); 
    AccountController target = new AccountController(repository); 
    //be able to set Membership underlying provider 
    Membership.Provider = new MockMembershipProvider(); 
} 

答えて

8

、このような何かをメンバーシップのインターフェイスを定義し、その後にそれを注入...

public class AspDotNetMembershipProvider : IMembershipProvider 
{ 
    public void CreateUser(string username, string password) 
    { 
     string createStatus; 

     Membership.CreateUser(
      username, 
      password, 
      username, 
      null, 
      null, 
      true, 
      null, 
      out createStatus); 

     // throw an exception if createStatus isn't as expected 
    } 
} 

あなたこのように使用してください:

public class AccountController 
{ 
    private readonly IMembershipProvider _membershipProvider; 

    public AccountController(IMembershipProvider membershipProvider) 
    { 
     this._membershipProvider = membershipProvider; 
    } 

    public ActionResult Register(RegistrationModel model) 
    { 
     // Try and catch this, returning a success ActionResult if it worked: 
     this._membershipProvider.CreateUser(model.Email, model.Password); 
    } 
} 

ASP.NETは多くのことに対してMembershipのような静的クラスを使用しますが、静的クラスアクセスは常にユニットテストを困難にします。標準的なソリューションは、サービスのインターフェイスを定義し、静的なASP.NETクラスを使用して実装し、それをコントローラに挿入することです。

デフォルトのDependencyResolverUnityのようなDIコンテナを使用して、注入をセットアップすることができます。

+1

は 'AspDotNetMembershipProvider'は、インターフェイスを実装していないでしょうか? 'public class AspDotNetMembershipProviderのように:IMembershipProvider {...' – marapet

+0

もちろん、それはすべきです。修正済み、ありがとう:) –

+0

'Membership'クラスは静的ですが、基礎となるプロバイダはaspランタイムによって設定されています...また、私もそれを設定できると考えていました –

0

コントローラのユニットテストでは、CustomMembershipProviderまたは標準のSQLプロバイダを使用しないでください。単体テストを実行する場合は、返すものを完全に制御できるStub/Fakeを使用する必要があります。テストで実際のプロバイダを使用している場合は、もはやユニットテストではなく、統合テストです。

ユニットのテスト容易性を実現するには、偽のプロバイダを定義する必要があります.Mockingフレームワークを使用するか、手動で缶詰の結果を偽造します。偽物はこのようなものになります:

public class FakeMembershipProvider : MembershipProvider 
{ 
    public MembershipCreateStatus CreateStatus = MembershipCreateStatus.Success; 

    public void CreateUser((string username, string password, string email, 
     string passwordQuestion, string passwordAnswer, bool isApproved, 
     object providerUserKey, out MembershipCreateStatus status) 
    { 
     status = CreateStatus; 
    } 

    ... 
} 

コントローラは、あなたがテストしたい内容に応じて設定をしたいユニットテストではCTOR引数

public class AccountController 
{ 
    private readonly MembershipProvider _membershipProvider; 

    public AccountController(MembershipProvider membershipProvider) 
    { 
     _membershipProvider = membershipProvider; 
    } 

    public ActionResult Register(RegistrationModel model) 
    { 
     MembershipCreateStatus result; 
     _membershipProvider.CreateUser(model.Email, model.Password, ..., out result); 

     return View(/*Make this depend on the result*/); 
    } 
} 

として偽のプロバイダを見てみましょうをし、 MembershipProviderは非常に大きく、あなたはおそらくそれをWiすることができ、それのすべてを使用するつもりはないので

[Test] 
void Should_display_success_view_when_user_successfully_created() 
{ 
    var membershipProvider = new FakeMembershipProvider(); 
    membershipProvider.CreateStatus = MembershipCreateStatus.Success; 
    var controller = new AccountController(membershipProvider); 
    var model = new RegistrationModel(); 

    var result = controller.Register(model) as ViewResult; 

    Assert.That(result.Name, Is.EqualTo("ExpectedViewName"));  
} 

:あなたは、各登録結果のために期待する成果を主張することができます@SteveWilkesのアプローチを使用して、より小さなターゲットインターフェイスを作成する代わりにMembershipクラスをラップします。また、嘲笑フレームワークはあなたに多くの仕事を節約します。新しい依存関係でコントローラを接続するには、新しいControllerFactoryを作成する必要があります。

2

私はより構造化されたメンバーシッププロバイダを作成しました。これは3つの異なるインターフェイスに分割されています(プロバイダはDependencyResolverを使用して解決しています)。

これは、プロバイダの単体テストを容易にします。 IAccountRepositoryの実装をテストするだけです。 http://blog.gauffin.org/2011/09/a-more-structured-membershipprovider/

をあるいは単にnugetパッケージインストール:あなたがここでそれについて読むことができます

install-package griffin.mvccontrib 
関連する問題