誰かがUserManager
とRoleManager
の成功したモックソリューションを考え出しましたか?私は一日中壁に頭を打ちました。 Entity Frameworkデータストアにアクセスするのではなく、メモリコレクションで使用するオブジェクトをモックするだけです。私はインターネットを精査し、MOQを使用していくつかの異なるアプローチを試みました。
私は、新しいものをテストする方がはるかに簡単だという印象を受けていました。何か不足していますか?
または、UserManager
が引数として受け入れる_IUserStore<TUser>
_インターフェイスをモックできます。
_var userStore = new Mock<IUserStore<ApplicationUser>>();
var userManager = new UserManager(userStore.Object);
_
@Joe Brunscheonが以下のコメントで述べているように、UserManagerはIUserPasswordStoreなどの他のインターフェイスのサポートを検出します。これらをmoqすることもできます。
_var passwordManager = userStore.As<IUserPasswordStore<ApplicationUser>>()
.Setup(...).Returns(...);
_
これらすべてを一度にmoqする必要はありません。テスト対象コードの必要に応じて、それらをmoqすることができます。実際には、EFがIUserStoreを実装するために使用するUserStoreは他のインターフェイスを実装し、UserManagerはこれらのインターフェイスが実装されているかどうかを確認するために内部検出を実行します。さいわい、moqを使用すると、.As<T>()
を使用して、多くのインターフェイスを実装できるサロゲートをモックアップできます。
つまり、Microsoft.AspNet.Identityを使用すると、コードでラッパーなしでそのまま使用するのに必要なすべてが提供されます。依存関係の注入を使用してUserManagerをインスタンス化する限り、ユニットテストでそれを消費するインターフェイスをモックアップし、他のインターフェイスのメソッドを内部的にサポートするために拡張された何らかの_IUserStore<T>
_ moqを介して渡すことで安全にモックできますUserManagerによって検出されました。
私は、asp.netコアで働くすべての人のために、この質問に対する解決策を更新したいと思います。
private Mock<UserManager<ApplicationUser>> GetMockUserManager()
{
var userStoreMock = new Mock<IUserStore<ApplicationUser>>();
return new Mock<UserManager<ApplicationUser>>(
userStoreMock.Object, null, null, null, null, null, null, null, null);
}
はい、8倍のヌルですが、これまでのところ、これ以上優雅な解決策はありません。他のパラメーターに興味がある場合は、 ソースコード をご覧ください。
Rubitoの answer を拡張するために、RoleManagerで行った方法を以下に示します。
public static Mock<RoleManager<ApplicationRole>> GetMockRoleManager()
{
var roleStore = new Mock<IRoleStore<ApplicationRole>>();
return new Mock<RoleManager<ApplicationRole>>(
roleStore.Object,null,null,null,null);
}
public class FakeUserManager : UserManager<User>
{
public FakeUserManager()
: base(new Mock<IUserStore<User>>().Object,
new Mock<IOptions<IdentityOptions>>().Object,
new Mock<IPasswordHasher<User>>().Object,
new IUserValidator<User>[0],
new IPasswordValidator<User>[0],
new Mock<ILookupNormalizer>().Object,
new Mock<IdentityErrorDescriber>().Object,
new Mock<IServiceProvider>().Object,
new Mock<ILogger<UserManager<User>>>().Object,
new Mock<IHttpContextAccessor>().Object)
{ }
public override Task<User> FindByEmailAsync(string email)
{
return Task.FromResult(new User{Email = email});
}
public override Task<bool> IsEmailConfirmedAsync(User user)
{
return Task.FromResult(user.Email == "[email protected]");
}
public override Task<string> GeneratePasswordResetTokenAsync(User user)
{
return Task.FromResult("---------------");
}
}
UserManagerまたはRoleManagerを直接モックすることはできません。ただし、できることは、それらを使用するオブジェクトのモックです。
例えば:
public interface IWrapUserManager
{
UserManager WrappedUserManager {get; set;}
//provide methods / properties that wrap up all UserManager methods / props.
}
public class WrapUserManager : IWrapUserManager
{
UserManager WrappedUserManager {get; set;}
//implementation here. to test UserManager, just wrap all methods / props.
}
//Here's a class that's actually going to use it.
public class ClassToTest
{
private IWrapUserManager _manager;
public ClassToTest(IWrapUserManager manager)
{
_manager = manager;
}
//more implementation here
}
M笑について:
[TestClass]
public class TestMock
{
[TestMethod]
public void TestMockingUserManager()
{
var mock = new Mock<IWrapUserManager>();
//setup your mock with methods and return stuff here.
var testClass = new ClassToTest(mock.Object); //you are now mocking your class that wraps up UserManager.
//test your class with a mocked out UserManager here.
}
}