Як перевірити або виключити приватний недоступний код з покриття коду

У мене є купа збірок з майже 100% тестовим покриттям, але я часто стикаюся з ситуацією, як у прикладі нижче. Я не можу перевірити випадок перемикання за замовчуванням, який є, щоб захистити від майбутніх помилок, де я додаю більше елементів до переліку, але забув оновити оператор switch для підтримки нових елементів.

Я хотів би мати змогу або знайти шаблон, яким я можу виключити цей "неперевірений" код, перевірити його чи позначити цю лінію коду (але не весь метод), щоб виключити аналіз покриття .

Це може здатися дурним, але я не хочу припускати, що випадок за замовчуванням ніколи не станеться, і я не хочу пов'язувати випадок за замовчуванням з тим, що вже існує. Я хочу, щоб виключення було викинуто, коли я створював такі помилки. Що станеться рано чи пізно.

Я використовую DotCover для розрахунку охоплення в даний момент.

Note: This is just example code but I think it illustrates a fairly common pattern.

public class Tester
{
    private enum StuffToDo
    {
        Swim = 0, 
        Bike,
        Run
    }

    public void DoSomeRandomStuff()
    {
        var random = new Random();
        DoStuff((StuffToDo)random.Next(3));
    }

    private void DoStuff(StuffToDo stuff)
    {
        switch (stuff)
        {
            case StuffToDo.Swim:
                break;
            case StuffToDo.Bike:
                break;
            case StuffToDo.Run:
                break;
            default:
               //How do I test or exclude this line from coverage?
                throw new ArgumentOutOfRangeException("stuff");
        }
    }
}
19
@ JakobMöllås те, що Келлі згадує тут, є головною причиною моєї відповіді. Ви можете подумати, що це те ж саме, що й інший код, у якому ви маєте ці перемикачі, але це дуже вказує, що ви використовували Random у прикладі, тобто клас має залежність, яка вносить додаткові проблеми з тестами.
додано Автор eglasius, джерело
Вам дійсно потрібно 100%? (~ 100% вже дуже добре)
додано Автор vc 74, джерело
Можливий дублікат stackoverflow.com/questions/113395/…
додано Автор David L, джерело
Хоча це лише приклад, я не погоджуюся, що це досить поширена закономірність. Кожен сценарій повинен прийматися окремо. У цьому конкретному випадку джерелом вашого болю є залежність від Random. Я б віддав перевагу інжектору генератора випадкових чисел (бажано Constructor).
додано Автор Kelly Ethridge, джерело
@DavidL Ні, як це питання так само, як і моє? У ньому розглядаються очікувані винятки в одиничних тестах.
додано Автор Jakob Möllås, джерело
@ vc74 Ні, але хотілося б, якщо це можливо. Це дуже легко побачити, якщо щось нове не перевіряється, якщо нормальний випадок становить 100%. Проте, цей конкретний випадок надовго мене заважав.
додано Автор Jakob Möllås, джерело
Випадок за замовчуванням є у випадку, якщо я оновлюю свою випадкову логіку, щоб бути, наприклад, 0-3. Тим не менш, це, звичайно, кілька надуманий приклад, але показує модель, на яку я часто стикаюся. Більш загальний випадок - це, можливо, переведення коду одного перекладу в інший. Я завжди дивуюся, як часто я вражаю ці «неможливі» випадки, особливо під час розробки.
додано Автор Jakob Möllås, джерело
Чому цей рядок коду в першу чергу - ви очікуєте, що random.Next (3) буде виробляти значення поза діапазоном 0-2?
додано Автор Shaun Wilde, джерело

10 Відповіді

Приватні методи завжди є кандидатами для вилучення у власні класи. Особливо, якщо вони тримають складну логіку, як ваша. Я пропоную вам зробити клас StuffDoer з DoStuff() як відкритий метод і ввести його в клас Tester . Тоді у вас є:

  • Метод DoStuff() , доступний за допомогою тестів
  • Метод DoSomeRandomStuff() , який можна протестувати за допомогою макета замість того, щоб покладатися на результат DoStuff() , що робить його справжнім тестовим блоком.
  • Немає порушення SRP.
  • Загалом, хороший, чіткий і твердий код.
7
додано
+1 Я дійсно погоджуюся з цим. З практичної сторони важко кидатися на прискорення при роботі з базовими кодами. Речі в моїх відповідях, як правило, є проміжним кроком для швидкого тестування застарілого коду.
додано Автор eglasius, джерело
@ JakobMöllås: З мого досвіду, всі ці маленькі методи роблять безлад класу з великою кількістю коду, який неможливо досягти тестами. При ретельному іменуванні, ієрархіях просторів імен та структурі папок, я віддаю перевагу невеликим класам, які поважають SRP, і легко перевіряються. IMHO, належне модульне тестування є, безумовно, найбільшим внеском у підтримуваний код.
додано Автор Morten, джерело
Згоден, це те, що я зазвичай роблю (з ін'єкцією або без нього). Однак, залежно від джерела переліку (наприклад, у загальному визначенні), може бути багато невеликих методів, як це. Іноді код буде просто складнішим і важче підтримувати, створюючи ці додаткові методи та класи ("Doers").
додано Автор Jakob Möllås, джерело
Це хороша порада, але не вирішує вихідну проблему: значення за замовчуванням на перемикачах перерахування нелегко покрити в модульних тестах. Перехід до шаблону Стратегії просто переносить проблему на творчу сторону. Запис у Вікіпедії для Factory Method або Abstract Factory страждає від того самого питання.
додано Автор micahtan, джерело

Ви можете використовувати директиву перед компілятором, використовуючи DEBUG, подібну до цього (або створіть власну):

#if DEBUG
    public void DoStuff(StuffToDo stuff)
#else
    private void DoStuff(StuffToDo stuff)
#endif
    {
        switch (stuff)
        {
            case StuffToDo.Swim:
                break;
            case StuffToDo.Bike:
                break;
            case StuffToDo.Run:
                break;
            default:
               //How do I test or exclude this line from coverage?
                throw new ArgumentOutOfRangeException("stuff");
        }
    }
3
додано
+1, чудовий підхід. Я б використовував спеціальну змінну і містив директиви компілятора навколо default або будь-якої найменшої області коду, яку потрібно виключити, а не навколо визначень методів, які важче читати і підтримувати
додано Автор Sten Petrov, джерело
Незважаючи на те, що я не знаходжу цього досить, якщо б я був змушений використовувати його, я б зробив це, використовуючи внутрішній модифікатор доступу, підписував збірки та використовував InternalsVisibleTo , щоб дозволити доступ до тесту тільки класи.
додано Автор Odys, джерело

Просто зробіть це.

private static int GetRandomStuffInt()
{
    var random = new Random();
    DoStuff((StuffToDo)random.Next(Enum.GetNames(typeof(StuffToDo)).Length));
}

Це гарантує, що номер, який він повертає, є частиною переліку, і тому ніколи не досягне перемикача default: . ( Посилання )

3
додано
За винятком того, що буде досягнутий за умовчанням, коли хтось по дорозі додасть нове значення до переліку.
додано Автор eglasius, джерело
Спасибі, хоча, як було зазначено, проблема не є точним прикладом, а проблемою, як перевірити ситуацію поза діапазоном в перемиканні методу DoStuff (або інших подібних).
додано Автор Jakob Möllås, джерело
Отримання випадкового переліку, як це, не працює, якщо ви використовуєте перелік із нестандартним замовленням .. наприклад, якщо ви хочете прапори, або перерви у ваших номерах з іншої причини. напр. a = 1, b = 3, c = 5.
додано Автор emragins, джерело
Ви перевірили код? В основному це масив, а коли додано або видалено значення, відповідним чином змінюється довжина масиву. Це не список, тому ви не можете додавати або видаляти елементи після компіляції. Хтось виправив мене, якщо я помиляюся.
додано Автор Dave, джерело
Ну з цим кодом ви не отримаєте обставин поза зоною дії, принаймні, ваш не повинен, тому не може бути причин перевіряти їх. У будь-якому випадку, я думаю, що це не було питання.
додано Автор Dave, джерело

Update: given the answers in here, it seems some important clarifications are needed.

  1. an enum doesn't prevent you from reaching the default clause, this is a valid way to reach it: DoStuff((StuffToDo)9999)
  2. the default clause isn't required in a switch statement. In that case, the code would just silently continue after the switch
  3. If the method was internal, you could use InternalsToVisible to unit test it directly
  4. You could refactor the code in such a way that the strategy handled in the switch can be reached by the unit tests, like @Morten mentions on his answer
  5. Random, dates and similar are a typical problem for unit tests, and what you do is to change the code in such a way that those can be replaced during unit tests. My answer is just one way of the many ways to do so. I show how you can inject it via a field member, but it could be via the constructor, and it can also be an interface if desired.
  6. If the enum wasn't private, my code sample below could instead expose a Func, which would make the tests a bit more readable.

Ви все ще можете зробити це і отримати 100%:

public class Tester
{
    private enum StuffToDo
    {
        Swim = 0, 
        Bike,
        Run
    }
    public Func randomStuffProvider = GetRandomStuffInt;

    public void DoSomeRandomStuff()
    {
        DoStuff((StuffToDo)randomStuffProvider());
    }
    private static int GetRandomStuffInt()
    {
        //note: don't do this, you're supposed to reuse the random instance
        var random = new Random();
        return random.Next(3);
    }

    private void DoStuff(StuffToDo stuff)
    {
        switch (stuff)
        {
            case StuffToDo.Swim:
                break;
            case StuffToDo.Bike:
                break;
            case StuffToDo.Run:
                break;
            default:
               //How do I test or exclude this line from coverage?
                throw new ArgumentOutOfRangeException("stuff");
        }
    }
}

ps. yes it exposes the RandomStuffProvider so that you can use in an unit test. I didn't make it Func because that's private.

2
додано
Я роздутий, просто дивлячись на це
додано Автор Sten Petrov, джерело
@varocarbas повторно пов'язує входи-> поведінку. Як я вже згадував, "останній зразок зазвичай хороший для цього типу коду (з різних причин)". Це ясно читається, коли ви маєте справу зі списками дій, і я використовував це та подібне у кількох випадках. Початкове питання залишається, однак, як ми можемо дістатися до гілки коду, яка викине виняток, який був би в іншому з цієї перевірки, якщо (accountedStuff.ContainsKey (stuff)), якщо ви не зміните поведінку.
додано Автор eglasius, джерело
@varocarbas справа в тому, що верхня відповідь розглядається як вирішення питання ОП. У вашій відповіді ви знайдете деякі хороші методи рефакторингу, які дуже корисні при роботі з цим типом коду, тому це дає можливість добре прочитати. Причина, яку я вважаю проблематичною на першому місці, полягає в тому, що в моєму досвіді зміна поведінки призводить до великих неприємностей у дикій природі; Деякі люди просто бачать верхню відповідь і застосовують це до своїх середовищ, не розуміючи при цьому ніяких наслідків. Повторно перевіряючи, технічно випадок робить це, таким чином, що може бути оптимізований компілятором.
додано Автор eglasius, джерело
@varocarbas про -1 голосів на голові. Це має сенс, якщо ви твердо вірите, що відповідь введе в оману людей, які прийдуть пізніше, шукаючи відповіді на деякі проблеми. Спеціально, якщо є краща відповідь (як у Мортена). Також зазвичай, якщо обидва відповіді знаходяться на однаковому рівні голосування, ви б просто підвищили той, який, на вашу думку, має бути там. Але якщо є 2 різниці голосів, це має сенс зробити це (так тепер обидва відповіді знаходяться на одному рівні).
додано Автор eglasius, джерело
Моя відповідь показує швидкий спосіб тестування навіть старих кодів. Для того, щоб правильно поглянути на відповідь @ Morten.
додано Автор eglasius, джерело
Ой, так, це саме те, що я мав на увазі. Правда, ця випадкова залежність від генератора видно. Зверніть увагу, що інший параметр робить його параметром конструктора. У всіх випадках ви дійсно бажаєте встановити передбачуване значення для випадкових у вашому модулі тестів, інакше ви не можете перевірити передбачуваний результат.
додано Автор eglasius, джерело
Право, це поточна поведінка. На своїх тестових одиницях ви можете перекрити його, щоб повернути фіксоване значення. Це дозволить вам мати надійні тести для значень 0-2, плюс ви можете встановити його на більш високе значення, яке призведе до того, що ваша умова за замовчуванням буде вражена.
додано Автор eglasius, джерело
@eglasius, ви говорите, що моя відповідь вводить в оману, і що слід видалити? Що вона не дає жодної цінної інформації (навіть прямо навпаки)? Я досить новий у цьому світі відповіді, і ви, здається, маєте досить довгий досвід. Якщо ви можете пояснити свою точку належним чином і довести, що запропонована альтернатива (попередньої перевірки вхідних даних, і, врешті-решт, зв'язування входів-> поведінки) не краще, ніж оригінальні проб і помилки + покладання на випадок за замовчуванням, від певності/З теоретичної точки зору, я міг би розглянути питання про видалення моєї відповіді.
додано Автор varocarbas, джерело
-1 тому, що я не думаю, що ви зрозуміли правильно це питання. Це не питання бути дійсно важливим чи ні; але це питання відповіді на запитання шляхом надання відповіді, що теоретично відповідає її вимогам. Ваша відповідь - це просто "не хвилюйтеся, все нормально", що, ІМО, взагалі не є відповіддю. ПРИМІТКА: Щоб бути чесний я подумав що -1 інше питання у bounty не являло собою правильну річ зробити (я є новий тут) та саме тому я не зробив це раніше; але ви довели мене неправильно і саме тому я це роблю зараз.
додано Автор varocarbas, джерело
Так, це те, що я хочу, але випадкова поведінка є лише прикладом. Це може бути просто загальною операцією перекладу - однією перерахуванням на іншу або щось подібне.
додано Автор Jakob Möllås, джерело
Я не впевнений, що я розумію, як це вирішить щось, постачальник у вашому прикладі просто повертає випадкове ціле число, правда?
додано Автор Jakob Möllås, джерело
Ага, я думаю, ви мали на увазі щось на зразок DoStuff ((StuffToDo) RandomStuffProvider ()); ? Інакше нічого не зміниться, наскільки я бачу. Проте, це додасть до цього публічного інтерфейсу постачальника, який виглядає трохи дивно, що не надто багато.
додано Автор Jakob Möllås, джерело

"Проблема", яку ви посилаєтеся, є внутрішнім для перемикання ... випадку, і тому найкраще, що ви можете зробити, щоб уникнути її, покладаючись на іншу альтернативу. Особисто мені не подобається занадто багато перемикання ... справа через його негнучкість. Таким чином, ця відповідь має на меті забезпечити альтернативу для перемикання висловлювань, здатних забезпечити нульову невизначеність, яку ви шукаєте.

У таких ситуаціях я, як правило, покладаюся на набір умов, взятих з масиву, заповненого на початку функції, який автоматично фільтруватиме будь-який неврахований вхід. Приклад:

private void DoStuffMyWay(StuffToDo stuff)
{
    StuffToDo[] accountedStuff = new StuffToDo[] { StuffToDo.Bike, StuffToDo.Run, StuffToDo.Swim };

    if (accountedStuff.Contains(stuff))
    {
        if (stuff == accountedStuff[0])
        {
            //do bike stuff
        }
        else if (stuff == accountedStuff[1])
        {
            //do run stuff
        }
        else if (stuff == accountedStuff[2])
        {
            //do swim stuff
        }
    }
}

Це, звичайно, не дуже елегантно, але я думаю, що я не елегантний програміст.

Оскільки, можливо, ви віддаєте перевагу іншому типу підходу до проблеми, у вас є інша альтернатива; вона менш ефективна, але виглядає краще:

private void DoStuffWithStyle(StuffToDo stuff)
{
    Dictionary accountedStuff = new Dictionary();
    accountedStuff.Add(StuffToDo.Bike, actionBike);
    accountedStuff.Add(StuffToDo.Run, actionRun);
    accountedStuff.Add(StuffToDo.Swim, actionSwim);

    if (accountedStuff.ContainsKey(stuff))
    {
        accountedStuff[stuff].Invoke();
    }
}

private void actionBike()
{
    //do bike stuff
}

private void actionRun()
{
    //do run stuff
}

private void actionSwim()
{
   //do swim stuff
}

За допомогою другого варіанту ви можете навіть створити словник як глобальну змінну і заповнити його разом з переліком.

2
додано
imho, це не правильна відповідь: 1. Обидва підходи змінюють поведінку (непідтримувані значення просто мовчки провалюються, що в моєму досвіді найгірше) 2. ОП може просто видалити умова за замовчуванням, і це буде точно так само 3 Перший зразок коду не повинен виконувати .ToString, просто зберігати значення перерахування в масиві і порівнювати перерахування 4. на більш пізньому коді, вам не потрібно явне нове дію, ви можете просто сказати, accountedStuff.Add (StuffToDo .Bike, actionBike). Тим не менш, останній зразок, як правило, добре для цього типу коду (з різних причин)
додано Автор eglasius, джерело
головне це точка 1 і 2. ВП явно висловив його в питанні: "це може звучати нерозумно, але я не хочу припускати, що випадок за замовчуванням ніколи не станеться, і я не хочу комплектувати справу за замовчуванням з однією Я хочу, щоб виключення було викинуто, коли я створював такі помилки. Що станеться рано чи пізно. ". ВП прав, пізніше хтось додасть ще одне значення до переліку, і пропустить оновлення. Ніякий виняток означає, що він залишиться непоміченим, тому він закінчується більшою неприємністю.
додано Автор eglasius, джерело
Отже, ви говорите, що у вашому коді має бути пропозиція else, щоб викинути виняток (таким чином повертаючись до початкової проблеми)? Але ви також стверджуєте, що мій номер 2 в оригінальному коментарі неправильний, я посилаюся на посилання на перемикач: msdn.microsoft.com/en-us/library/06tc147t (v = vs.80) .aspx " Якщо мітка за замовчуванням відсутня, керування передається поза перемикачем. ". Я бачу, це те, що ви мали на увазі з "проблема" ви посилаєтеся внутрішньо перемикається ... справа "; ну, ні, це не так.
додано Автор eglasius, джерело
2. ОП може просто видалити умову за замовчуванням, і це буде точно так само - з практичної точки зору це буде точно так само, але не з теоретичної точки зору, поставленого в цьому питанні; це означає, що деякі випадки (дефолтні) не будуть враховані (малоймовірно, в тому випадку, коли "не будучи там").
додано Автор varocarbas, джерело
Непідтримувані значення просто замовчуються? Як це може бути правдою? Ви говорите, що кожна умова, яка використовується в коді, який не виконується, означає невдачу? Я думав, що істина/помилка є двома можливими результатами для умови, і тому жоден з них не може вважатися тригером помилки. Не могли б ви пояснити свою точку зору краще?
додано Автор varocarbas, джерело
3. Перший зразок коду не повинен робити. ToString, просто зберігати enum значення в масиві і порівняти переліку -> Ви маєте рацію, але я не очікував, що це буде розглядатися як помилка (навіть не наполовину) .
додано Автор varocarbas, джерело
4. на більш пізньому коді, вам не потрібні явні нові дії, ви можете просто сказати, accountedStuff.Add (StuffToDo.Bike, actionBike); -> OK, те ж саме, що і для попередньої точки; не усвідомлюючи, що це може розглядатися як щось неправильне.
додано Автор varocarbas, джерело
@eglasius Я відредагував відповідь, щоб відповісти на ваші пропозиції (ті, які я вважав актуальними), спасибі. У будь-якому випадку, я хотів би почути правильне пояснення вашого "мовчазного провалу".
додано Автор varocarbas, джерело
Я зрозуміла питання: він шукає спосіб переконатися, що будь-яка можливість є (теоретично) під контролем. Моя відповідь ґрунтується на думці, що така мета не може бути досягнута, спираючись на висловлювання перемикача ... case, яке за визначенням включає твердження за замовчуванням. Я запропонував альтернативу, що забезпечує 100-відсоткову впевненість: не існує ситуації дефолту/неврахування; умова завжди дасть впевненість: якщо вона є, зробіть це; якщо його немає, викликайте помилку (через інше); обидві форми поведінки (вона існує чи ні) - це правильні/прямі/певні виходи з умови.
додано Автор varocarbas, джерело
Випадок за замовчуванням повинен подбати про будь-яку проблему, це зрозуміло. Тоді в чому причина цього питання? З теоретичної точки зору, переконавшись, що будь-яка ситуація врахована, маючи повну впевненість у тому, що код виконується тільки тоді, коли даний випадок перерахунку враховується функцією. Практично мій підхід і випадок перемикання дають таку саму відповідь? Так. Теоретично, випадок перемикання враховує все як умова заголовка? Мій підхід перевіряє, чи слід аналізувати даний вхід; випадок перемикання аналізує його в будь-якому випадку.
додано Автор varocarbas, джерело

Я згоден з Nate тут вище. Це, напевно, найпростіше (StuffToDo.None). Як альтернативу можна також перевантажити метод, подібний до цього:

    private void DoStuff(StuffToDo stuff)
    {
        DoStuff(stuff.ToString());
    }

    private void DoStuff(string stuff)
        switch (stuff)
        {
            case "Swim":
                break;
            case "Bike":
                break;
            case "Run":
                break;
            default:
                throw new ArgumentOutOfRangeException("stuff");
        }
    }

Тоді ви можете перевірити ситуацію, яку ви охоплюєте у вашій стандартній заяві.

2
додано
Вам не потрібно робити це, щоб мати змогу досягти умовчання
додано Автор eglasius, джерело
див. оновлення в моїй відповіді, як це зробити
додано Автор eglasius, джерело

Це недоступний код, тому що тип перемикача - Enum, і ви кодували всі можливі випадки. Ніколи не буде випадків "За замовчуванням".

Ви можете додати 'Невідоме' або деяке додаткове перечислення, яке не повинно мати відповідного випаду випадок, тоді це попередження піде.

private enum StuffToDo
{
    Swim = 0, 
    Bike,
    Run,
   //just for code coverage
   //will never reach here
    Unknown
}

Code Coverage does not go into depth of evaluating every possibility, so it is not question of testing it. It matches code pattern based on their precoded expected behaviour

Покриття коду вважає це таким чином, ви додали всі можливості існуючого перерахування, ніякого способу за замовчуванням не буде викликатися. Так налаштовується їхнє правило, ви не можете змінити їхнє правило.

1
додано
Ви можете досягти його навіть без Невідомого, побачити моє оновлення
додано Автор eglasius, джерело

Напишіть тести, які перевіряють значення поза діапазоном і очікують винятку.

1
додано
Отже, можна додати значення синтаксису до StuffToDo , наприклад, StuffToDo.None або щось подібне, тоді має бути значення за умовчанням , хоча як і раніше значення стану помилки.
додано Автор Nate Diamond, джерело
Так, це також призведе до виникнення помилки, але не завжди має сенс мати таке значення. І це може навіть не бути можливим, якщо декларація перерахування не виходить з коду, який я можу змінити. Навіть із значенням за замовчуванням (значення помилки) я все ще хочу перевірити його.
додано Автор Jakob Möllås, джерело
І як мені краще це зробити в моєму випадку?
додано Автор Jakob Möllås, джерело

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

Дивлячись на ваш код інше почуття, яке я отримую, ваш загальнодоступний метод не приймає ніяких вхідних даних і не дає жодної інформації, але робить модифікацію, яка не виглядає правильно. Схоже, що це мовчки змінює речі, які можуть заплутати.

Спробуйте скористатися більш конкретним методом, який чітко визначає, що він приймає як вхідні дані та як це змінюється.

1
додано
Спасибі, хоча я не хочу змінювати підпис, це одна з причин, чому я маю це питання. Насправді моя проблема більш складна, ніж мій приклад, звичайно, і іноді включає кілька проектів на декількох мовах. Визначення перерахування може бути спільним і написано мета-мовою, пізніше компілюватися в C# і включати крок вручну для оновлення коду відповідно до останнього визначення. Такі речі важко автоматизувати і обійти. Загалом, просте рішення полягає в тому, щоб розбити приватний метод на внутрішній метод, який дозволить мені перевірити всі випадки.
додано Автор Jakob Möllås, джерело

Мій Resharper також "скаржиться" на недоступний код, який мені не подобається під час програмування. Назвіть мене анальним, але мені подобається позбавлятися від мертвого коду з того моменту, як я його бачу.

Для вашої справи я б вибрав один із цих випадків як випадок за умовчанням, і поставте його на такий вигляд:

    private void DoStuff(StuffToDo stuff)
    {
        switch (stuff)
        {
            case StuffToDo.Swim:
                break;
            case StuffToDo.Bike:
                break;
            case StuffToDo.Run:
            default:
                break;
        }
    }

Оскільки ви прагнете до 100% тестового покриття, в ідеалі, це має порушуватися, коли ви додаєте перерахування, яке слід розглядати по-різному.

І якщо ви дійсно хочете бути впевненими, ви все ще можете його пом'якшити:

    private void DoStuff(StuffToDo stuff)
    {
        switch (stuff)
        {
            case StuffToDo.Swim:
                break;
            case StuffToDo.Bike:
                break;
            case StuffToDo.Run:
            default:
                if (stuff != StuffToDo.Run) throw new ArgumentOutOfRangeException("stuff");
                break;
        }
    }
0
додано
проблема з першим зразком коду полягає в тому, що, коли хтось додає нове значення, DoStuff просто запустить "Run" і ніколи не повідомляє про будь-які проблеми. Це ускладнює пошук проблеми. На другому зразку коду, ви маєте те ж саме, що і OP, гілка коду, яка повинна бути вражена модульними тестами.
додано Автор eglasius, джерело
var chat = new Chat();
var chat = new Chat();
642 учасників

Обсуждение вопросов по C# / .NET / .NET Core / .NET Standard / Azure Сообщества-организаторы: — @itkpi — @dncuug