バックグラウンド:
新しい雇用主の厳格な単体テスト要件に従って、単体テストの経験を積むことに取り組んでいますが、単体テスト全体は私にとって初めてです。に依存しているため、ASP.NET Identity を利用するメソッドをテストしようとすると、大量の問題が発生しました。
HttpContext.Current.GetOwinContext().Authentication
と
HttpContext.Current.GetOwinContext().GetUserManager
現在、この現在のプロジェクトでは、これまでのところインターフェイスと依存性注入を十分に活用していませんが、組織の Active Directory システムを ID データベースに組み込む一環として (有効な Active でログインしたときにユーザー テーブルに行を作成します)。ディレクトリ資格情報、およびそれ以降はそれらの ID データベースを使用する)、私はインターフェイスと Ninject を使用して ID 側を改良し、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 = "ttestingly@test.com",
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;
}
このテストを (さまざまな TestCases のすべてに対して) 実行すると、次の例外が返されます。
System.NotSupportedException: データベースにモデル メタデータが含まれていないため、モデルの互換性を確認できません。モデルの互換性は、Code First または Code First Migrations を使用して作成されたデータベースに対してのみ確認できます。
これは_identityContext.Users.Add(_user);
この問題について私が見たすべてのことは、データベースに接続しようとしてコードが実行されている間にデータベースへの接続が開かれていることが原因であることを示していますが、これはそうではないと思います。 -既存のデータベース (そうではありません: これを確認するために、テストの合間にデータベースを複数回削除しました)。
注: 現在、私たちのチームのデータベースはすべて localhost データベースであるため、他の誰も私のものをいじることはありません。
解決策が接続文字列を変更することであるこの例を見てきましたが、この問題は単体テストでのみ発生します-実行中に、インターフェイスを組み込むために行った変更の前に、アプリケーションのすべてが期待どおりに機能することを確認しました、Ninject、および Active Directory - したがって、接続文字列自体が問題だとは思いませんが、関連する接続文字列を次に示します
(これらは適切な XML ですが、Stack Overflow で適切に表示する方法がわかりません。だから私はすべての中かっこを削除しました):
connectionStrings
add name="ADUUserDB" providerName="System.Data.SqlClient" connectionString="Data Source=localhost\sql2014;Initial Catalog=ADUUserDB;Integrated Security=True;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False; MultipleActiveResultSets =True"
/connectionStrings