Мокинг внутренних классов с помощью Moq для модульного тестирования

Скажем, у меня есть класс «ClassA», который зависит от класса «ClassB» (введен в конструктор ClassA). Я хочу издеваться над ClassB, чтобы тестировать ClassA изолированно. Оба класса внутренние.

Поправьте меня, если я ошибаюсь, но похоже, что Moq может издеваться над классом только в том случае, если он общедоступный, у него есть общедоступный конструктор без параметров, а методы, которые нужно высмеивать, public virtual. Я действительно не хочу делать эти классы общедоступными. Мне что-то не хватает с Moq, или он просто не подходит для того, что я хочу делать?

Думаю, я мог бы создать интерфейс (скажем, «IClassB»), который реализует ClassB, внедрить его в ClassA и вместо этого смоделировать интерфейс. ClassB все еще может быть внутренним (хотя я понимаю, что методы интерфейса должны быть общедоступными). Хотя это сработает, мне неловко создавать множество интерфейсов, единственная цель которых - поддерживать имитацию модульных тестов. Мысли?


person Andrew Stephens    schedule 10.07.2013    source источник


Ответы (1)


Вы можете сделать внутренние компоненты видимыми для Moq, добавив _1 _ в файле assembly.cs вашего проекта, например:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

Почему "DynamicProxyGenAssembly2", а не "Moq"? Это имя динамической сборки, созданной для хранения динамически генерируемых типов прокси (все это обрабатывается еще одной библиотекой, Castle's DynamicProxy), которая используется Moq. Таким образом, вы предоставляете типы динамической сборке прокси, а не самому Moq.

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

Думаю, я мог бы создать интерфейс (скажем, «IClassB»), который реализует ClassB, внедрить его в ClassA и вместо этого смоделировать интерфейс.

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

person k.m    schedule 10.07.2013
comment
Полезно знать, спасибо. Однако теперь я решил оставить классы общедоступными (по крайней мере, те, которые проходят тестирование). Думаю, я зациклился на попытках сделать все внутренним, но это всего лишь настольное приложение, поэтому оно не так важно, как это было бы (скажем) в сборке / API, которые предоставлялись клиентам. - person Andrew Stephens; 10.07.2013
comment
Очень полезный пост, я был очень смущен тем, что InternalsVisibleTo (IntegrationTests) не работал. Тогда стало понятно, что к нему обращается не моя сборка, а динамически созданная сборка Касла. - person Chris Marisic; 13.04.2016