2010-05-05 3 views
17

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

Редактировать: На самом деле я новичок в Moq. У меня есть много классов и методов классов для тестирования с использованием Moq. Многие классы являются внутренними, многие из них имеют внутренние методы, многие из них не имеют виртуальных методов. И не может изменить подпись на методах и классах. Может кто-нибудь, пожалуйста, дайте мне знать, как пройти тестирование этого сценария с помощью Moq. Или, пожалуйста, предложите мне другую структуру тестирования, с которой легко учиться и легко работать.

ответ

2

Почему вы хотите издеваться над внутренним методом?

Если вам нужно высмеять внутренний метод, скажем, чтобы обойти зависимость или взаимодействие, возможно, вам стоит подумать о перепроектировании класса.

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

Я не верю, что существует ясный путь к непубличной насмешке с Моком.

Но, если вам абсолютно необходимо, вы можете использовать TypeMock Isolator, чтобы издеваться над чем угодно.

Кроме того, он так и не заблудился: Томас связал хорошую статью о том, как использовать бесплатные MS Moles, чтобы высмеять непубличных участников.

Mocking the Unmockable: Using Microsoft Moles with Gallio

+1

Действительно, насмешливый частные методы типична код запах. – mikek

+5

Я категорически не согласен: если вы делаете TDD, то насмешливое внутреннее вещание - обычное, повседневное ... –

+0

@Thomas - Я понимаю вашу точку зрения. Но вы должны понимать, что классическая стратегия определяется как тестирование поведения классов, как правило, с помощью интерфейса, а не его внутренняя реализация, поскольку это тесно связывает ваши тесты с внутренней реализацией и вызывает инерцию и поломку при рефакторинге. Я должен сказать, что вы в меньшинстве, с вашим мнением. примечание: я прочитал немного вашего блога и знаю, что вы достаточно вдумчивы, и TDD вам дорог - я просто не согласен с вашими разногласиями. ;-) –

1

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

Если вы считаете необходимым изменить метод, чтобы сделать класс проверяемым, реорганизовать класс, чтобы сложная часть стала зависимой или иным образом подменялась параметром или подклассом.

+0

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

3

Не с Moq.

Но вы можете использовать бесплатный Moles framework из MS, чтобы делать такие вещи. Я написал об этом здесь: Mocking the Unmockable: Using Microsoft Moles with Gallio. (это относится не только к Галлио, но и дает хорошее общее впечатление о том, что вы можете сделать с Moles ...). Другой альтернативой будет Typemock ...

HTH. Thomas

+0

+ для записи на бесплатные инструменты –

+1

Неправильно (по крайней мере, в 2016 году). См. Ответ Дарина. – mhvelplund

+0

С 2016 года MS Moles заменена MS Fakes, согласно http://wayback.archive.org/web/20160316031214/http://research.microsoft.com/en-us/projects/moles/. – clacke

0

Если вам нужно проверить много кода, который вы не можете изменить, лучше начать с MS Moles или TypeMock с самого начала.

Бесплатные смешные фреймворки, такие как Moq, дают вам поддержку по интерфейсам и виртуальным методам. Не звучит, как если бы вы уедешь с этим ...

Томас

55

Вы можете легко фиктивные внутренние виртуальные методы, добавив следующие строки в AssemblyInfo.CS:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] // namespace in Moq 
[assembly: InternalsVisibleTo("YourTestClass")] 

Если сборка сильно по имени, вам необходимо включить открытый ключ для DynamicProxyGenAssembly2 (Спасибо на комментарий @bvgheluwe; источник: Moq quickstart guide):

[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2,PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] 

Я не понимаю, почему в принятом ответе говорится, что вы никогда не должны этого делать. Разве это не то, что вы делаете, когда используете метод инъекции «Извлечение и переопределение» (локальный заводский метод), описанный Роем Ошеровым в Chapter 3 of The Art Of Unit Testing?

+1

Это очень помогло мне. Спасибо! – Fabian

+9

Это должен быть принятый ответ. Это еще одна дискуссия о том, является ли насмешка над внутренним методом правильной вещью, но если вы решили, что это то, что вы хотите сделать, это способ ее достижения. – CraigTP

+2

Это не сработает. Вам также нужен открытый ключ. – max

22

Марк метод, как internal *protected* (также виртуальный, конечно)

+2

omg, вы решили его. – max

+0

Это работает, но можете ли вы сказать нам, почему это работает? – MrLore

+1

@MrLore это работает, потому что «_protected_ internal» означает, что метод может быть доступен подклассом в _any_ assembly, и если вы пометите его «virtual», то ваш издевательский подкласс может предоставить пользовательскую реализацию. – andreister

Смежные вопросы