Visual Studio позволяет модульное тестирование частных методов через автоматически сгенерированный класс средства доступа. Я написал тест частного метода, который успешно компилируется, но во время выполнения он не работает. Довольно минимальная версия кода и теста:
//in project MyProj
class TypeA
{
private List<TypeB> myList = new List<TypeB>();
private class TypeB
{
public TypeB()
{
}
}
public TypeA()
{
}
private void MyFunc()
{
//processing of myList that changes state of instance
}
}
//in project TestMyProj
public void MyFuncTest()
{
TypeA_Accessor target = new TypeA_Accessor();
//following line is the one that throws exception
target.myList.Add(new TypeA_Accessor.TypeB());
target.MyFunc();
//check changed state of target
}
Ошибка во время выполнения:
Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'.
Согласно intellisense - и, следовательно, я предполагаю, что цель компилятора - имеет тип TypeA_Accessor. Но во время выполнения он имеет тип TypeA, и, следовательно, добавление списка завершается неудачно.
Есть ли способ, как я могу остановить эту ошибку? Или, возможно, более вероятно, что другие советы дают другие люди (я предсказываю, может быть, «не тестируйте частные методы» и «не используйте юнит-тесты для управления состоянием объектов»).
c#
unit-testing
Дзюнъитиро
источник
источник
Ответы:
Да, не тестируйте частные методы .... Идея модульного теста состоит в том, чтобы протестировать модуль с помощью его открытого «API».
Если вы обнаружите, что вам нужно протестировать много личного поведения, скорее всего, у вас есть новый «класс», скрывающийся внутри класса, который вы пытаетесь протестировать, распакуйте его и протестируйте с помощью открытого интерфейса.
Один совет / инструмент мышления ..... Существует идея, что ни один метод не должен быть приватным. Это означает, что все методы должны жить в общедоступном интерфейсе объекта ... если вы считаете, что вам нужно сделать его закрытым, он, скорее всего, живет на другом объекте.
Этот совет не совсем работает на практике, но в основном это хороший совет, и часто он заставляет людей разлагать свои объекты на более мелкие.
источник
Вы можете использовать PrivateObject Class
источник
«Ничто не называется стандартом или лучшей практикой, возможно, это просто популярные мнения».
То же самое относится и к этой дискуссии.
Все зависит от того, что вы считаете модулем, если вы думаете, что UNIT - это класс, тогда вы будете использовать только открытый метод. Если вы думаете, что UNIT - это строки кода, использование частных методов не заставит вас чувствовать себя виноватым.
Если вы хотите вызывать приватные методы, вы можете использовать класс «PrivateObject» и вызвать метод invoke. Вы можете посмотреть это подробное видео на YouTube ( http://www.youtube.com/watch?v=Vq6Gcs9LrPQ ), которое показывает, как использовать «PrivateObject», а также обсуждает, является ли тестирование частных методов логичным или нет.
источник
Другая мысль заключается в том, чтобы расширить тестирование на «внутренние» классы / методы, придавая больше смысла этому тестированию. Вы можете использовать InternalsVisibleToAttribute на сборке, чтобы представить их отдельным модулям модульного тестирования.
В сочетании с закрытым классом вы можете приблизиться к такой инкапсуляции, что тестовый метод виден только из сборки unittest ваших методов. Учтите, что защищенный метод в закрытом классе де-факто является частным.
И юнит тест:
источник
Один из способов проверить приватные методы - это рефлексия. Это относится и к NUnit и XUnit:
источник
call methods
статический и нестатический ?Э-э-э ... Пришел сюда с точно такой же проблемой: протестировать простой , но ключевой частный метод. После прочтения этой темы, похоже, что «я хочу просверлить эту простую дыру в этом простом куске металла, и я хочу убедиться, что качество соответствует спецификациям», а затем приходит «Хорошо, это не так просто. Прежде всего, нет подходящего инструмента для этого, но вы можете построить обсерваторию гравитационных волн в своем саду. Прочитайте мою статью на http://foobar.brigther-than-einstein.org/ Во-первых, конечно, вы Я должен посещать некоторые курсы квантовой физики, тогда вам понадобятся тонны ультра-холодного азотия, и, конечно же, моя книга доступна на Amazon "...
Другими словами...
Нет, обо всем по порядку.
Каждый метод, будь то частный, внутренний, защищенный, публичный, должен быть тестируемым. Должен быть способ внедрить такие тесты без лишних слов, как было представлено здесь.
Зачем? Именно из- за архитектурных упоминаний, сделанных некоторыми авторами. Возможно, простое повторение принципов программного обеспечения может устранить некоторые недоразумения.
В этом случае обычные подозреваемые: OCP, SRP и, как всегда, KIS.
Но подожди минутку. Идея сделать все публично доступным является скорее менее политической и некой позицией. Но. Когда дело доходит до кода, даже в тогдашнем Open Source Community, это не догма. Вместо этого «сокрытие» чего-либо является хорошей практикой, чтобы облегчить знакомство с определенным API. Например, вы бы скрыли основные расчеты вашего нового рыночного стандартного блока цифровых термометров - не для того, чтобы скрыть математику за реальной измеряемой кривой для любопытных читателей кода, но чтобы предотвратить зависимость вашего кода от некоторых, возможно, неожиданно важные пользователи, которые не смогли устоять перед тем, чтобы использовать свой ранее закрытый, внутренний защищенный код для реализации своих собственных идей.
О чем я говорю?
Легко объявить Эру Водолея или то, что сейчас называют, но если мой сенсорный датчик получит от 1,0 до 2,0, реализация Translate ... может измениться от простого линейного уравнения, которое легко понять и применимый "для всех", к довольно сложным вычислениям, использующим анализ или что-то еще, и поэтому я бы нарушил чужой код. Зачем? Потому что они не понимали сами принципы программного кодирования, даже KIS.
Короче говоря: нам нужен простой способ проверить приватные методы - без лишних слов.
Первое: всех с новым годом!
Второе: репетируйте уроки своего архитектора.
Третье: «публичный» модификатор - это религия, а не решение.
источник
Другой вариант, который не был упомянут, - это просто создать класс модульного теста в качестве дочернего объекта тестируемого объекта. Пример NUnit:
Это позволит легко тестировать приватные и защищенные (но не унаследованные приватные) методы и позволит вам хранить все ваши тесты отдельно от реального кода, чтобы не развертывать тестовые сборки в рабочей среде. Переключение ваших личных методов на защищенные методы будет приемлемым для многих унаследованных объектов, и это довольно простое изменение.
ТЕМ НЕ МЕНИЕ...
Хотя это интересный подход к решению проблемы тестирования скрытых методов, я не уверен, что буду выступать за то, чтобы это было правильным решением проблемы во всех случаях. Кажется немного странным проводить внутреннее тестирование объекта, и я подозреваю, что могут быть некоторые сценарии, когда этот подход взорвет вас. (Например, неизменяемые объекты могут сделать некоторые тесты действительно сложными).
Хотя я упоминаю этот подход, я хотел бы предположить, что это скорее мозговая атака, чем законное решение. Возьми это с зерном соли.
РЕДАКТИРОВАТЬ: Я нахожу действительно веселым, что люди голосуют за этот ответ, так как я явно описываю это как плохую идею. Значит ли это, что люди соглашаются со мной? Я так растерялся.....
источник
Из книги « Эффективная работа с устаревшим кодом» :
По словам автора, способ исправить это - создать новый класс и добавить метод as
public
.Автор объясняет далее:
Таким образом, в этих пределах ваш единственный реальный вариант - создать метод
public
в текущем или новом классе.источник
TL; DR: Извлечь приватный метод в другой класс, протестировать на этом классе; Узнайте больше о принципе SRP (принцип единой ответственности)
Кажется, вам нужно извлечь
private
метод в другой класс; в этом должно бытьpublic
. Вместо того, чтобы пытаться проверитьprivate
метод, вы должны проверитьpublic
метод этого другого класса.У нас есть следующий сценарий:
Нам нужно проверить логику
_someLogic
; но похоже, что ониClass A
играют больше роли, чем нужно (нарушают принцип ПСП); просто рефакторинг на два классаТаким способом
someLogic
можно было протестировать на A2; в A1 просто создайте поддельный A2, а затем введите его в конструктор, чтобы проверить, что A2 вызывается для функции с именемsomeLogic
.источник
В VS 2005/2008 вы можете использовать приватный аксессор для тестирования приватного члена, но этот путь исчез в более поздней версии VS
источник