Подтвердить что ты не робот

Издевательский новый пользовательский интерфейс Microsoft Entity Framework UserManager и RoleManager

Кто-нибудь придумал удачное издевательское решение для UserManager и RoleManager? Я весь день бил головой о стену. Все, что я хочу сделать, - это обмануть объекты для использования в коллекции памяти, а не попадания в хранилище данных Entity Framework. Я просмотрел интернет и попробовал несколько разных подходов с помощью MOQ.

У меня создалось впечатление, что новый материал намного легче тестировать. Я что-то пропустил?

4b9b3361

Ответ 1

Кроме того, вы можете IUserStore<TUser> интерфейс IUserStore<TUser> который UserManager принимает в качестве аргумента.

var userStore = new Mock<IUserStore<ApplicationUser>>();
var userManager = new UserManager(userStore.Object);

Как отмечает @Joe Brunscheon в комментарии ниже, UserManager обнаруживает поддержку других интерфейсов, таких как IUserPasswordStore и т.д. Вы также можете выполнить следующие действия:

var passwordManager = userStore.As<IUserPasswordStore<ApplicationUser>>()
    .Setup(...).Returns(...);

Вам не нужно выставлять все эти данные сразу, вы можете просто помагать их по мере необходимости с помощью кода. На самом деле, UserStore, который использует EF для реализации IUserStore, реализует другие интерфейсы, а UserManager будет выполнять внутреннее обнаружение, чтобы убедиться, что эти интерфейсы реализованы, и, следовательно, поддерживаются дополнительные функции. К счастью, moq позволяет вам макетировать суррогат, который может реализовать множество интерфейсов, используя .As<T>().

Короче говоря, Microsoft.AspNet.Identity дает вам все, что вам нужно, чтобы использовать его без оболочки без кода в вашем коде. До тех пор, пока вы используете инъекцию зависимостей для создания экземпляра UserManager, вы можете спокойно протестировать его в модульных тестах, высмеивая интерфейсы, которые он потребляет, и передавая их через какой-то IUserStore<T> moq, который дополняется для поддержки методов на других обнаруженных внутри интерфейса с помощью UserManager.

Ответ 2

Мне нравится обновлять решение этого вопроса для тех, кто работает с ядром 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 раз null, но до сих пор нет более изящного решения. Если вас интересуют другие параметры, посмотрите исходный код.

Ответ 3

Вы не сможете напрямую подключать 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 a class that actually going to use it.
public class ClassToTest
{
    private IWrapUserManager _manager;
    public ClassToTest(IWrapUserManager manager)
    {
        _manager = manager;
    }
    //more implementation here
}

На насмешку:

[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.
    }
}

Ответ 4

Чтобы развернуть ответ Rubito, вот как я сделал это для RoleManager:

public static Mock<RoleManager<ApplicationRole>> GetMockRoleManager()
{
   var roleStore = new Mock<IRoleStore<ApplicationRole>>();
   return new Mock<RoleManager<ApplicationRole>>(
                roleStore.Object,null,null,null,null);

}

Ответ 5

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("---------------");
        }
    }