Может кто-нибудь уточнить мое понимание концепции проверки Verify? - PullRequest
2 голосов
/ 07 марта 2011

Я играю с некоторыми юнит-тестами и издевательствами.Я пытаюсь проверить, что какой-то код в моем методе был вызван.Я не думаю, что я понимаю Verify часть насмешливого права, потому что я могу только когда-либо Проверять основной метод ... который глуп, потому что это то, что я Act в любом случае.

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

Позволяет использовать этот пример, чтобы выделить то, что я делаю неправильно.

public interface IAuthenticationService
{
    bool Authenticate(string username, string password);
    SignOut();
}

public class FormsAuthenticationService : IAuthenticationService
{
    public bool Authenticate(string username, string password)
    {
        var user = _userService.FindSingle(x => x.UserName == username);
        if (user == null) return false;

        // Hash their password.
        var hashedPassword = EncodePassword(password, user.PasswordSalt);

        if (!hashedPassword.Equals(password, StringComparison.InvariantCulture))
            return false;

        FormsAuthentication.SetAuthCookie(userName, true);
        return true;
    }
}

Итак, теперь я хочу убедиться, что

  • EncodePassword был вызван.
  • FormsAuthentication.SetAuthCookie(..) был вызван.

Теперь, я не забочусь о последствиях обоих.И что более важно, я не хочу тестировать эти методы.Это должно быть обработано в другом месте.Что я должен сделать, так это убедиться, что эти методы были вызваны и ... если это возможно ... ожидаемый результат был возвращен.

Правильное ли это понимание того, что означает "Подтвердить" с насмешкой?

Если так, может кто-нибудь показать мне, как я могу это сделать.Желательно с moq, но я чем-нибудь доволен.

Ответы [ 3 ]

6 голосов
/ 07 марта 2011

Обычно вы (по крайней мере, IMO) должны быть насмешливыми зависимостями, а не другими методами в тестируемом классе. Например, у вас может быть интерфейс IPasswordEncoder, который используется для вызова EncodePassword. Вы могли бы высмеять , что , и убедиться, что метод был вызван ... но в том же классе это не имеет особого смысла.

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

4 голосов
/ 07 марта 2011

На мой взгляд, у вас есть две проблемы:

  1. EncodePassword принадлежит FormsAuthenticationService, что делает его труднее издеваться.Существует два возможных решения этой проблемы:

    1. Сделать виртуальный пароль EncodePassword виртуальным и создать Mock<FormsAuthenticationService>.В этом случае вы сможете Verify EncodePassword.
    2. Извлекать кодирование пароля в другой сервис, так как оно все равно не связано с реализацией аутентификации.
  2. FormsAuthentication.SetAuthCookie(..) - статический метод.Одним из разумных решений здесь является использование дополнительного сервиса, который полностью упаковывает FormsAuthentication, но не делает ничего, кроме этого, поэтому вам не придется его тестировать.

2 голосов
/ 08 марта 2011

В тестовой разработке вы очень редко хотите утверждать, что частный метод вызывается. Что означает проверка того, что EncodePassword называется действительно тестом? Если мы посмотрим на метод в деталях, то увидим, что, например, я могу изменить метод, чтобы отбрасывать результат вызова EncodePassword без прерывания теста . Это, конечно, не правильно - тест стал слишком гибким и бесполезным. Вместо этого рассмотрите эти два способа обойти это.

Тестирует открытый интерфейс класса

Это то, что вы обычно хотите. Вас действительно волнует, что этот метод вызывается или нет? Метод Authenticate что-то делает, мы хотим проверить, что этот метод делает то, что должен. Возможно, такое утверждение, чтобы проверить, что неправильный пароль не аутентифицируется:

Assert.That(service.Authenticate("Pure.Krome", "wrong pass"), Is.False);

Это позволяет вам реорганизовать класс легче, не нарушая тесты. Также документирует мощность теста увеличивается - Как этот класс предполагается использовать?

Извлечение функциональности метода в его собственный класс

Иногда закрытый метод класса должен вызываться не во время теста, а скорее как имитация. Например, статический вызов метода FormsAuthentication.SetAuthCookie(userName, true) может иметь побочные эффекты или может выдавать, если он не запущен на веб-сервере или чем-то подобном. В этом случае, по моему опыту, лучше всего ввести интерфейс, описывающий необходимые функции. В этом случае, например, ICookieTarget с методом SetAuthCookie, который может быть посмешищем.

...