Насмешливый UserPrincipal - PullRequest
       6

Насмешливый UserPrincipal

5 голосов
/ 22 августа 2011

У меня есть класс, который обрабатывает изменения пароля и проверки истечения срока действия для почтовых ящиков обмена.Я проверяю LastPasswordSet на UserPrincipal.

А как насчет TDD?

Я хочу проверить, правильно ли мой класс обрабатывает проверки пароля, написав несколько тестов.Но я не могу понять, как я мог бы высмеивать UserPrincipal.FindByIdentity (PrincipalContext, [некоторое имя пользователя]).

Я собираюсь написать метод, который возвращает true / false, если пароль был изменен,последние 90 днейПоэтому я хотел бы издеваться над UserPrincipal, чтобы в своих тестах я мог установить возвращаемое значение LastPasswordSet просто для проверки логики, которую я собираюсь написать для «уведомления о необходимости изменения пароля».

Ответы [ 4 ]

10 голосов
/ 20 декабря 2012

Я понимаю, что это старый пост, но недавно я столкнулся с той же проблемой, что и оригинальный постер, и после прочтения ответа я подумал, что мне придется сделать то же самое.Я не хочу, чтобы кто-то еще читал этот пост и терял драгоценное время, как я, поэтому я решил по-настоящему ответить на этот пост.

Поняв, что не существует простого способа обернуть функциональность UserPrincipal и не полагаться на интеграционные или сквозные тесты, как это было предложено, я вспомнил, что есть способ имитировать статические классы.С учетом вышесказанного ниже точно, как это сделать, используя Telerik JustMock .

private void MockUserPrincipal()
    {
        //Mock principal context
        var context = Mock.Create<PrincipalContext>((action) => action.MockConstructor());

        //Mock user principal
        var user = Mock.Create(() => new UserPrincipal(context));           

        //Mock the properties you need
        Mock.Arrange(() => user.Enabled).Returns(true);
        Mock.Arrange(() => user.UserPrincipalName).Returns("TestUser");
        Mock.Arrange(() => user.LastPasswordSet).Returns(DateTime.Now);

        //Mock any functions you need
        Mock.Arrange(() => user.IsAccountLockedOut()).Returns(false);

        //Setup static UserPrincipal class
        Mock.SetupStatic<UserPrincipal>();

        //Mock the static function you need
        Mock.Arrange(() => UserPrincipal.FindByIdentity(Arg.IsAny<PrincipalContext>(), Arg.AnyString)).Returns(user);  

        //Now calling UserPrincipal.FindByIdentity with any context and identity will return the mocked UserPrincipal
    }
4 голосов
/ 22 августа 2011

Я отвечу на это с содержательной фразой

"Не издевайтесь над типами, которые вам не принадлежат"

не удалось найти авторитетный блог, подтверждающий это. Пример ссылки .Хотя это, кажется, приписывают Джо Уолнесу.

UserPrincipal, если я помню, это .NET Framework, связанный с аутентификацией.Типы насмешек, которые находятся вне вашего контроля (могут изменяться), могут привести к хрупким тестам.

Вместо этого выясните, чего хочет ваш дизайн от UserPrincipal

  • найдите роль, которую UserPrincipal выполняет или реализует косвенночерез TDDing клиентов
  • Смоделируйте эту роль в своих модульных тестах и ​​протестируйте всех вызывающих.
  • Имейте «интеграционные тесты», чтобы убедиться, что ваша реальная реализация нажимает нужные кнопки на UserPrincipal при вызове.
  • Положитесь на сквозные / приемочные тесты, чтобы найти ошибки, которые возникают, когда все компоненты соединены вместе.
2 голосов
/ 03 июня 2015

Старый пост, но есть рабочий пример.Даже если вы никогда не проверяете чужой код, вы хотите проверить свои методы.А вашим методам могут потребоваться данные из UserPrincipal, возвращаемые другим методом.Теперь скажите, что вам нужно проверить свойство LastPasswordSet.

  1. Щелкните правой кнопкой мыши на .dll System.DirectoryServices.AccountManagement в вашем проекте модульного тестирования.Выберите «Add Fakes Assembly».
  2. Добавить этот юнит-тест

    [TestMethod]
    public async Task ActiveDirectoryUserFactory_CreateUserAsyncAndWhatYouExpect()
    {
        // Arrange
        using(ShimsContext.Create())
        {
            var userPrincipal = new System.DirectoryServices.AccountManagement.Fakes.ShimUserPrincipal();
            var baseUserPrincipal = new System.DirectoryServices.AccountManagement.Fakes.ShimAuthenticablePrincipal(userPrincipal);
    
    
            baseUserPrincipal.LastPasswordSetGet = () => DateTime.Now;
    
            // Mock the returned UserPrincipal to use our userPrincipal, here's for Moq
            _class.Setup(x => x.GetUserAsync("param"))
                .Returns(Task.FromResult<UserPrincipal>(userPrincipal));
    
    
            // Act, your method that gets your shimUserPrincipal from _class.GetUserAsync in your _target class (I understood you got the UserPrincipal from external source)
            var user = await _target.YourMethod();
    
            // Assert
            Assert.IsNull(user);
        }
    
    }
    
    // method that does the code you want to test
    public async Task<Object> YourMethod()
    {
        var user = await _class.GetUserAsync("param");
        var lastLogin = user.LastPasswordSet;
        return new Object()
    }
    

Существует множество источников для Shims, поэтому я позволю этомуэтот.Надеюсь, что это помогает кому-то, кто гуглит "издеваться над UserPrincipal".

1 голос
/ 22 августа 2011

Боюсь, класс UserPrincipal не совсем подходит для TDD.
А как насчет того, чтобы обернуть нужную вам функциональность в свой класс, и вместо этого посмеяться над этим?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...