none
Тестирование приватных методов класса RRS feed

  • Вопрос

  • Всем привет. Читая stackoverflow постоянно вижу, что попытка протестировать приватные методы класса - это нехорошо. Что тестировать нужно только открытый интерфейс. Да и вообще ни в одном тесте просто так нельзя взять и вызвать приватный метод.

    Я начал делать класс, написал кое-какой функционал, теперь хочу написать тесты. У меня всего один открытый метод пока, все остальное внутренние дела класса. Типа, инкапсуляция, сокрытие реализации, все дела, умных слов набрался, как их применить не понимаю)))

    Поэтому, пожалуйста, объясните на кошках как протестировать вот такой класс(на реализацию методов особо можно не обращать внимания, я ведь их не тестировал, не знаю, правильно они работают или нет):

    internal class DumpReader
        {
            DirectoryInfo DumpDir { get; set; }
            FileStream DumpStream { get; set; }
            StreamReader Reader { get; set; }
            FileInfo[] DumpFiles { get; set; }
            private Int32 _index;
            private Int32 Index
            {
                get
                {
                    if (_index >= DumpFiles.Count())
                        _index = 0;
                    return _index;
                }
                set { _index = value; }
            }
    
            public DumpReader(string dumpDir)
            {
                DumpDir = new DirectoryInfo(dumpDir);
                DumpFiles = DumpDir.GetFiles();
                Index = 0;
            }
            private String GetString()
            {
                if (Reader == null || Reader.EndOfStream)
                    NextFile();
                return Reader.ReadLine();
            }
            private void NextFile()
            {
                DumpStream = new FileStream(DumpFiles[Index++].FullName, FileMode.Open);
                Reader = new StreamReader(DumpStream);
            }
            public Byte[] Read()
            {
                return StringToBytes();
            }
            private Byte[] StringToBytes()
            {
                var bytesString = GetString();
                var stringBytes = bytesString.Split('-');
                var bytes = new Byte[stringBytes.Length];
                for (var i = 0; i < bytes.Length; i++)
                {
                    bytes[i] = Convert.ToByte(stringBytes[i], 16);
                }
                return bytes;
            }
        }

    • Изменено pingvincible 7 ноября 2014 г. 17:59
    7 ноября 2014 г. 17:52

Ответы

  • Не надо тестировать ненужное. Если приватный метод нельзя протестировать через использующий его открытый интерфейс - метод не нужен. Когда появится необходимость использовать приватные методы в публичном, вот тогда их всех и тестировать.
    • Помечено в качестве ответа pingvincible 10 ноября 2014 г. 4:07
    7 ноября 2014 г. 21:57

Все ответы

  • Не надо тестировать ненужное. Если приватный метод нельзя протестировать через использующий его открытый интерфейс - метод не нужен. Когда появится необходимость использовать приватные методы в публичном, вот тогда их всех и тестировать.
    • Помечено в качестве ответа pingvincible 10 ноября 2014 г. 4:07
    7 ноября 2014 г. 21:57
  • Что значит метод не нужен? Его нужно заинлайнить в место вызова, или вы имеете ввиду, что его не надо тестировать?

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

    8 ноября 2014 г. 8:36
  • Ну почему косвенно?  Если тесты написаны правильно, и публичный метод их проходит, значит, приватные методы внутри него работают так, как надо.
    8 ноября 2014 г. 9:53
  • спасибо, я понял!
    10 ноября 2014 г. 4:07
  • Разные гуру наперебой говорят, что нет нужды тестировать закрытые методы, т. к. достаточно протестировать публичный интерфейс. Отчасти это так, ведь в момент вызова внутреннего члена может быть нарушен инвариант класса. Но на мой взгляд, тут просто сказывается отсутствие простого способа сделать это, как ключевое слово friend в языке C++.

    Как вариант можно private методы сделать internal, добавив в сборку атрибут InternalsVisibleToAttribute, что даст к ним доступ сборке юнит-тестов.

    При желании можно использовать рефлексию - она позволяет вызывать и приватные методы.

    Также можно посмотреть в сторону фреймворка Microsoft Fakes. Он позволяет творить чудеса, мокая что угодно, хоть закрытые члены, хоть статические. Однако, я знаком с ним лишь понаслышке, поэтому практические советы не дам.

    10 ноября 2014 г. 9:36