2016-07-01 12 views
2

背景:発行ユニットテストEF&ASP.NETアイデンティティ - 非サポート例外:モデルの互換性

私は私の新しい雇用者の厳格なユニットテストの必要条件に従って、ユニットテストでいくつかの経験を得ることに取り組んでいますが、全体としてユニットテスト私には新しいものです。私は今、この現在のプロジェクトを持っているため、

HttpContext.Current.GetOwinContext().Authentication

HttpContext.Current.GetOwinContext().GetUserManager

への依存に、ASP.NETアイデンティティを利用する方法のいずれかをテストしようとしている問題のTONがありましたこれまでのところインターフェイスと依存関係注入を十分に活用していませんでしたが、組織のActive DirectoryシステムをIDデータベースに組み込む(ユーザーが有効なActive Directory資格情報でログインしたときにUsersテーブルに行を作成し、それ以降のアイデンティティデータベース)、私はアイデンティティの改訂に取り組んできました私たちのテストユニットテストプロジェクトにFakeItEasyを追加しました。

これは、実際には偽装するのではなく、実際のデータベース自体を使用するテストを生成していることを意味します。これは悪い習慣であり、最初の実際のプロジェクトに取り組んでいる間に、新しい人の心を過負荷にしないために単純に行われました。私たちは、これが原因で発生するねじれの大部分(すべて/すべて)を解決しました。

質問:
ユニットテストに次のメソッドをしようとしているときに、私は独特の問題に実行しています:

public bool ResetPassword(User user) 
    { 
     if (!user.EmailConfirmed) return false; 

     user.RequirePasswordReset = true; 
     string randomGeneratedPassword = GenerateRandomPassword(20); // defined at end of class 
     user.PasswordHash = hash.HashPassword(randomGeneratedPassword); 

     if (!UpdateUser(user)) return false; 

     string message = "We have received a request to reset your password. <br /><br />" + 
      "Your new password is shown below. <br /><br />" + 
      $"Your new password is: <br />{randomGeneratedPassword}<br /><br />" + 
      "This password is only valid for one login, and must be changed once it is used. <br /><br /><br /><br />" + 
      "Server<br />AmTrust Developer University"; 

     SendFormattedEmail(user.Email, user.FullName, message, "Your password has been reset"); 
     return true; 
    } 

私は(省略テストケースで)そうすることをこれまでに書かれているテストは次のとおりです。

public bool ResetPasswordTests(bool emailConfirmed) 
    { 
     //arrange 
     _user = new User() 
     { 
      Email = "[email protected]", 
      EmailConfirmed = emailConfirmed, 
      FirstName = "Test", 
      isActive = true, 
      isActiveDirectoryAccount = false, 
      LastName = "Testingly", 
      PasswordHash = _hash.HashPassword("secret1$"), 
      RequirePasswordReset = false, 
      UserName = "ttestingly" 
     }; 

     string hashedPass = _user.PasswordHash; 

     _identityContext.Users.Add(_user); 
     _identityContext.SaveChanges(); 

     //Suppress the email sending bit! 
     A.CallTo(() => _userBusinessLogic_Testable.SendFormattedEmail(null, null, null, null, null)) 
     .WithAnyArguments() 
     .DoesNothing(); 

     //act 
     bool result = _userBusinessLogic_Testable.ResetPassword(_user); 

     //assert 
     Assert.That(result); 
     Assert.That(_user.PasswordHash != hashedPass); 
     Assert.That(_user.RequirePasswordReset); 
     return result; 
    } 

(その様々なテストケースの全てに対して)このテストを実行するには、次の例外を返し

System.NotSupportedException: データベースにモデルメタデータが含まれていないため、モデルの互換性を確認できません。モデルの互換性は、コードファーストまたはコードファーストマイグレーションを使用して作成されたデータベースに対してのみチェックすることができます。

これは私がこの問題について見てきたすべてが「私はドンれ、コードがそのデータベースに接続しようとして実行している間に、それがデータベースへのオープン接続によって引き起こされていることを示し_identityContext.Users.Add(_user);

によって引き起こされますt と思われる場合は、と思われます。また、既存のデータベースをEFで管理しようとしている場合もあります(これは当てはまりません。

注:現在、私たちのチームのデータベースはすべてローカルホストデータベースであるため、私のものを乱しているデータベースはありません。

これは解決策が接続文字列を変更する場合の例ですが、この問題は単体テストでのみ発生します。実行中にアプリケーションのすべてが変更前に正常に動作することを確認しました私は接続文字列自体は問題ではないと思うが、ここでは関連する接続文字列
(彼らは適切なXMLですが、私はそれらを表示する方法をよく分かりません

のconnectionStrings
名を追加= "ADUUserDB" providerNameで= "System.Da:適切にスタックオーバーフローの上に、私は括弧のすべてを)削除しましたta.SqlClient "connectionString ="データソース= localhost \ sql2014;初期カタログ= ADUUserDB;統合セキュリティ= True;接続タイムアウト= 15; Encrypt = False; TrustServerCertificate = False; MultipleActiveResultSets = True」を
/のconnectionStrings

+2

私はこれを2つの別々の質問に入れる方がよいと思います。 –

答えて

2

私は、データベースのものに関する情報をしたんが、私はA.CallToためのアイデアを持っていると思う。FakeItEasyは、拡張メソッドである、Singleを設定するように依頼された時に不幸です。あなただけのフェイクを設定する必要があります。おそらく、

A.CallTo(() => _userBusinessLogic.GetUsers(null, null, null, null, null, null, null)) 
           .WithAnyArguments() 
           .Returns(new [] { _user }); 

公平に通常A.CallTo内側に一つだけのメソッド呼び出しがあるとき、これはアップしますので、それはだが、FakeItEasyは問題であなたを指しているのより良い仕事を(行うことができます少しは分かりやすい)。これを追跡するにはissue 786を入力してください。

+2

ありがとう、ブレア、その特定の場合の問題でした。アプリケーション全体でこのタイプの呼び出しを使用すると、非常にうれしいです。 私は今、投稿のその部分を削除しました。 –

2

私はこの問題が何であるかを考え出しました。それは簡単な設定問題でした。テストしようとしていたBLLで使用されていたリポジトリを実際に偽造していませんでした。私は直前に働いていたデータベースコンテキストにまっすぐにスキップしていましたが、何らかの理由で私が当時持っていた新しい、部分的に偽装された設定では失敗していました。

だから、私がしなければならなかったの変更は簡単だった:A.CallToで偽造され、関連する基本的なリポジトリのコールと
private IUserRepository _userRepository = A.Fake<IUserRepository>();
();

これにより、データベースに追加する必要がなくなり、テストの最後にエラーがスローされた場所が削除されます。

関連する問題