Вы правы, полагая, что создание отдельных сборок / проектов для изоляции тестового кода от рабочего кода является нормой в среде .NET. Я действительно поощряю эту практику при наставлении людей о модульном тестировании, потому что я не хочу, чтобы тестовый код смешивался с моим рабочим кодом.
Вообще говоря, я крайне неохотно проверяю закрытые / защищенные методы моего SUT. Самое замечательное в TDD / UnitTesting заключается в том, что вы описываете внешнее поведение и оставляете детали реализации гибкими и «черными». После этого вы можете выполнять столько рефакторингов, сколько считаете нужным, и до тех пор, пока они не нарушают внешнее поведение, тесты менять не нужно.
Если вы каким-то образом привязаны к деталям реализации (наследование, доступ к приватным / защищенным методам из производственной сборки), ваши тесты должны будут подвергаться рефакторингу так часто, как меняются внутренние детали класса. *
Иногда у вас может быть внутренний класс / метод, который вы хотите проверить. В этом случае вы можете использовать атрибут [assembly: InternalsVisibleTo («Имя сборки сборки»)]] в файле рабочей сборки AssemblyInfo.cs и разрешить вашей пробной сборке просматривать внутренние компоненты вашей сборки сборки.
InternalsVisibleToAttribute в MSDN
Следует отметить, что если вы новичок в .NET, внутренняя спецификация доступа отличается от частной и защищенной. Внутренний класс "public" внутри сборки, в которой он находится.
Надеюсь, что это отвечает на ваши вопросы.