Ложные .NET классы с использованием классов-обёрток - PullRequest
5 голосов
/ 27 марта 2011

У меня есть класс, который берет экземпляр MethodInfo и извлекает из него некоторую информацию, но я хотел бы посмеяться над этим классом.На данный момент это сложно, потому что для этого требуется MethodInfo, поэтому я планировал создать оболочку для класса MethodInfo и реализовать интерфейс для него.Например:

public interface IMethodInfo
{
    string Name { get; }
}

public class MethodInfoProxy : IMethodInfo
{
    private readonly MethodInfo _method;
    public MethodInfoProxy(MethodInfo method)
    {
        _method = method;
    }

    public string Name { get { return _method.Name; } }
}

public class MyClass
{
    public MyClass(IMethodInfo method)
    {
        ...
    }
}

Другим примером может быть метод File.Exists.Смысл в том, чтобы создать IFile.Exists и поместить его в класс FileProxy, который просто делегирует File.Exists.

Поскольку я новичок во всем мире модульного тестирования, я хотел бы знать, еслибудет считаться хорошим подходом для принятия?

Ответы [ 5 ]

3 голосов
/ 27 марта 2011

У вас есть два варианта:

  1. Используйте фальшивый фреймворк, такой как Microsoft Moles или TypeMock Isolator , который может макетировать статические и запечатанные классы. Это здорово, потому что вы не заканчиваете тем, что изменяете свой код только для того, чтобы изолировать тестируемый код от его зависимостей.
  2. Определение интерфейсов для поведения, которое вы хотите смоделировать, а затем создание реализации по умолчанию, которая оборачивает статический вызов или другие трудно тестируемые API-интерфейсы. Это подход, который вы предложили, и который я часто использовал. Ключевым моментом при определении этих интерфейсов является передача реальной / фиктивной реализации интерфейса в тестовый класс посредством некоторой формы внедрения зависимостей - обычно внедрения конструктора. Некоторые люди делают ошибку, создавая объект в тестируемом классе, и это делает невозможным его тестирование. Хорошее эмпирическое правило заключается в том, что когда вы видите объекты, создаваемые в вашем бизнес-коде, тогда это запах кода - не всегда плохая вещь, но определенно что-то, что нужно смотреть с подозрением. Об этом материале есть отличное видео: The Clean Code Talks - "Глобальное государство и одиночные игры" .

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

1 голос
/ 27 марта 2011

Я рекомендую попробовать вытащить зависимости из класса - вместо предоставления MethodInfo (или прокси), просто укажите Name.

Если это непрактично, вы можете либо написать прокси-классы, которые используют интерфейс адаптера (как вы предложили), либо использовать инструмент черной магии, такой как TypeMock или Moles (просто шучу над частью черной магии: я просто не имею опыта работы с ними). ​​

Если вы планируете использовать прокси-подход, обязательно посмотрите на библиотеку SystemWrapper , которая уже обрабатывает около двадцати классов из фреймворка .NET.

0 голосов
/ 27 августа 2013

Для более быстрого создания классов-оболочек вы можете использовать один из созданных мной генераторов кода Scaffold.

https://www.nuget.org/packages/Digitrish.WrapperGenerator/

Это создаст Интерфейс, который вы можете использовать для любой моделируемой среды и конкретного класса-оболочки для реальной реализации.

0 голосов
/ 27 марта 2011

Класс Mock (или фальшивый класс) будет классом, который вы создаете для удовлетворения зависимостей и делаете свой тест более детерминированным, исключая проблемы в ваших зависимостях.

public interface IMethodInfo
{
    string Name { get; }
}

Ваш класс моделирования:

FakeMethodInfo : IMethodInfo
{
 string Name {get {return "FakeMethod";}}
}

Теперь, в своем модульном тесте, передайте класс FakeMethodInfo, где вам нужен IMethodInfo.

Вся цель в том, что вы знаете, что FakeMethodInfo просто возвращает строку, так что есличто-то не получается, это - это не проблема.


Не знаю, какой контекст у MethodInfo в вашей программе.Лучшим примером будет

interface IUser
{
 string UserName {get;}
}

Если бы оно было реализовано в классе, вы бы получили реальное имя пользователя из базы данных.

Теперь, если вы создадите поддельное имя и передадите еговокруг, вы как бы моделируете пользователя, вошедшего в систему без реального пользователя, и исключаете, что любая проблема связана с `IUser.

Посмотрите этот большой ответ, который я опубликовал, о том, почему вы будете использовать насмешку.И пример с Moq.:

Разница между внедрением зависимостей и Mocking Framework (Ninject vs RhinoMock или Moq)

0 голосов
/ 27 марта 2011

Вы можете создать оболочку для каждого класса, который вы используете, но это будет очень дорого.Лучше использовать фальшивый фреймворк, такой как фреймворк Moles от Microsoft http://research.microsoft.com/en-us/projects/pex/, который также может блокировать статические методы.

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