Как вы тестируете приватные методы?

Мне нравится проверять, является ли он iset и если он пуст в тройном операторе.

// POST variable check
$userID  = (isset( $_POST['userID'] )    && !empty( $_POST['userID'] ))   ? $_POST['userID']   :  null;
$line    = (isset( $_POST['line'] )      && !empty( $_POST['line'] ))     ? $_POST['line']     :  null;
$message = (isset( $_POST['message'] )   && !empty( $_POST['message'] ))  ? $_POST['message']  :  null;
$source  = (isset( $_POST['source'] )    && !empty( $_POST['source'] ))   ? $_POST['source']   :  null;
$version = (isset( $_POST['version'] )   && !empty( $_POST['version'] ))  ? $_POST['version']  :  null;
$release = (isset( $_POST['release'] )   && !empty( $_POST['release'] ))  ? $_POST['release']  :  null;
468
задан Eric Labashosky 3 January 2018 в 20:43
поделиться

13 ответов

При использовании .net необходимо использовать InternalsVisibleToAttribute.

119
ответ дан Raedwald 3 January 2018 в 20:43
поделиться
CC -Dprivate=public

"CC" является компилятором командной строки в системе, которую я использую. -Dfoo=bar делает эквивалент #define foo bar. Так, этот параметр компиляции эффективно изменяет весь частный материал на общественность.

2
ответ дан Samuel Liew 3 January 2018 в 20:43
поделиться

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

Класс:

...

protected void APrivateFunction()
{
    ...
}

...

Подкласс для тестирования:

...

[Test]
public void TestAPrivateFunction()
{
    APrivateFunction();
    //or whatever testing code you want here
}

...
50
ответ дан Jason Jackson 3 January 2018 в 20:43
поделиться

Тесту MS создали хорошую функцию в этом, делает членов парламента, не занимающих официального поста и методы доступными в проекте путем создания файла, названного VSCodeGenAccessors

[System.Diagnostics.DebuggerStepThrough()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TestTools.UnitTestGeneration", "1.0.0.0")]
    internal class BaseAccessor
    {

        protected Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject m_privateObject;

        protected BaseAccessor(object target, Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType type)
        {
            m_privateObject = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject(target, type);
        }

        protected BaseAccessor(Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType type)
            :
                this(null, type)
        {
        }

        internal virtual object Target
        {
            get
            {
                return m_privateObject.Target;
            }
        }

        public override string ToString()
        {
            return this.Target.ToString();
        }

        public override bool Equals(object obj)
        {
            if (typeof(BaseAccessor).IsInstanceOfType(obj))
            {
                obj = ((BaseAccessor)(obj)).Target;
            }
            return this.Target.Equals(obj);
        }

        public override int GetHashCode()
        {
            return this.Target.GetHashCode();
        }
    }

С классами, которые получают из BaseAccessor

такой как

[System.Diagnostics.DebuggerStepThrough()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TestTools.UnitTestGeneration", "1.0.0.0")]
internal class SomeClassAccessor : BaseAccessor
{

    protected static Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType m_privateType = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType(typeof(global::Namespace.SomeClass));

    internal SomeClassAccessor(global::Namespace.Someclass target)
        : base(target, m_privateType)
    {
    }

    internal static string STATIC_STRING
    {
        get
        {
            string ret = ((string)(m_privateType.GetStaticField("STATIC_STRING")));
            return ret;
        }
        set
        {
            m_privateType.SetStaticField("STATIC_STRING", value);
        }
    }

    internal int memberVar    {
        get
        {
            int ret = ((int)(m_privateObject.GetField("memberVar")));
            return ret;
        }
        set
        {
            m_privateObject.SetField("memberVar", value);
        }
    }

    internal int PrivateMethodName(int paramName)
    {
        object[] args = new object[] {
            paramName};
        int ret = (int)(m_privateObject.Invoke("PrivateMethodName", new System.Type[] {
                typeof(int)}, args)));
        return ret;
    }
8
ответ дан Marcus King 3 January 2018 в 20:43
поделиться

На CodeProject существует статья, которая кратко обсуждает за и против тестирования закрытых методов. Это тогда обеспечивает некоторый отражательный код для доступа к закрытым методам (подобный коду, который Marcus обеспечивает выше.) Единственная проблема, которую я нашел с образцом, - то, что код не принимает во внимание перегруженные методы.

можно найти статью здесь:

http://www.codeproject.com/KB/cs/testnonpublicmembers.aspx

5
ответ дан Pedro 3 January 2018 в 20:43
поделиться

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

  1. , Если метод требуется протестировать, действительно стоит протестировать, может стоить для перемещения его в его собственный класс.
  2. Добавляют больше тестов к открытым методам, которые называют закрытый метод, тестируя функциональность закрытого метода. (Как комментаторы указали, необходимо только сделать это, если функциональность этих частных методов является действительно частью в с открытым интерфейсом. Если они на самом деле выполняют функции, которые скрыты от пользователя (т.е. модульный тест), это, вероятно, плохо).
342
ответ дан Jeroen Heijmans 3 January 2018 в 20:43
поделиться

Объявите их internal, и затем используйте InternalsVisibleToAttribute , чтобы позволить Вашему блоку модульного теста видеть их.

4
ответ дан James Curran 3 January 2018 в 20:43
поделиться

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

4
ответ дан swilliams 3 January 2018 в 20:43
поделиться

Я также использовал метод InternalsVisibleToAttribute. Стоит упомянуть также, что, если Вы чувствуете себя, неловко делая Ваши ранее закрытые методы внутренними для достижения этого, тогда возможно, они не должны быть предметом прямых модульных тестов так или иначе.

, В конце концов, Вы тестируете поведение из Вашего класса, а не это определенная реализация - можно изменить последнего, не изменяя первого, и тесты должны все еще передать.

10
ответ дан philsquared 3 January 2018 в 20:43
поделиться

MbUnit получил красивую оболочку для этого под названием Reflector.

Reflector dogReflector = new Reflector(new Dog());
dogReflector.Invoke("DreamAbout", DogDream.Food);

Вы также можете устанавливать и получать значения из свойств.

dogReflector.GetProperty("Age");

Что касается «частного теста», я согласен, что ... в идеальном мире. нет смысла делать частные модульные тесты. Но в реальном мире вы, возможно, захотите написать частные тесты вместо рефакторинга кода.

2
ответ дан 22 November 2019 в 22:51
поделиться

Иногда бывает полезно проверить частные объявления. По сути, у компилятора есть только один открытый метод: Compile (string outputFileName, params строка [] sourceSFileNames). Я уверен, вы понимаете, что такой метод будет сложно протестировать, не проверяя каждое «скрытое» объявление!

Вот почему мы создали Visual T #: для упрощения тестов. Это бесплатный язык программирования .NET (совместимый с C # v2.0).

Мы добавили оператор '.-'. Просто веди себя как '.' оператор, за исключением того, что вы также можете получить доступ к любому скрытому объявлению из ваших тестов, ничего не меняя в тестируемом проекте.

Взгляните на наш веб-сайт: скачать это бесплатно .

3
ответ дан 22 November 2019 в 22:51
поделиться

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

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

Так родился AccessPrivateWrapper - http://amazedsaint.blogspot.com/2010/05/accessprivatewrapper-c-40-dynamic.html - это класс быстрой оболочки, который сделает работу легко использовать динамические функции C # 4.0 и отражение.

Вы можете создавать внутренние / частные типы, например

    //Note that the wrapper is dynamic
    dynamic wrapper = AccessPrivateWrapper.FromType
        (typeof(SomeKnownClass).Assembly,"ClassWithPrivateConstructor");

    //Access the private members
    wrapper.PrivateMethodInPrivateClass();
17
ответ дан 22 November 2019 в 22:51
поделиться

Вы можете сгенерировать тестовый метод для приватного метода из Visual studio 2008. Когда вы создаете модульный тест для частного метода, в ваш тестовый проект добавляется папка Test References и в эту папку добавляется аксессор. Аксессор также упоминается в логике метода модульного теста. Этот аксессор позволяет вашему модульному тесту вызывать частные методы в коде, который вы тестируете. Подробности смотрите на

http://msdn.microsoft.com/en-us/library/bb385974.aspx

0
ответ дан 22 November 2019 в 22:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: