2010-05-05 18 views
17

Tengo una clase que tiene un método interno y quiero burlarme del método interno. Pero no puedo simularlo, es decir, no está llamando a la función de burlarse sino llamando a la función original. ¿Hay alguna forma de lograr esto?¿Cómo burlarse del método interno de una clase?

Editar: En realidad soy un principiante para el Moq. Tengo muchas clases y métodos de las clases para probar usando el Moq. Muchas clases son internas, muchas tienen métodos internos, muchas tienen métodos no virtuales. Y no puede cambiar la firma en los métodos y clases. ¿Puede alguien decirme cómo proceder para probar este escenario utilizando Moq? O bien, por favor sugiérame algún otro marco de prueba que sea fácil de aprender y fácil de usar.

Respuesta

2

¿Por qué te gustaría burlarte de un método interno?

Si encuentra la necesidad de burlarse de un método interno, por ejemplo, para eludir una dependencia o una interacción, quizás deba considerar el rediseño de la clase.

Inversion of Control y Dependency Injection son algunas posibles estrategias de diseño que pueden reducir el acoplamiento y aumentar la cohesión de sus clases y eliminar la necesidad de burlarse de los métodos internos.

No creo que haya un camino claro hacia la burla no pública con Moq.

Pero, si es absolutamente necesario, puede usar TypeMock Isolator para burlarse de cualquier cosa.

Además, para que no se pierda en el fragor: Thomas vinculó un buen artículo sobre el uso de los MS Moles gratuitos para burlarse de los miembros no públicos.

Mocking the Unmockable: Using Microsoft Moles with Gallio

+1

De hecho, el imitar métodos privados es olor código típico. – mikek

+5

Estoy totalmente en desacuerdo: si haces TDD, burlarse de las cosas internas es algo cotidiano ... –

+0

@Thomas - Entiendo tu punto de vista. Pero debe tener en cuenta que la estrategia clásica se define como probar el comportamiento de una clase, generalmente por interfaz, en lugar de su implementación interna, ya que esto relaciona estrechamente sus pruebas con la implementación interna e induce inercia y rotura al refactorizar. Debo decir que eres una minoría con tu opinión. Nota: He leído un poco de su blog y sé que es bastante considerado y que TDD es querido para usted. Simplemente no estoy de acuerdo con su desacuerdo. ;-) –

1

Prueba de la unidad debe probar la interfaz de una clase. Puede simular dependencias, pero los detalles de implementación de la clase en sí (como los métodos privados) deben probarse como parte de toda la clase, no por separado, y no cambiados para la prueba (de lo contrario, estaría probando una unidad diferente y luego realmente ser usado).

Si cree que es necesario cambiar el método para hacer que la clase sea comprobable, refactorice la clase para que la parte difícil se convierta en una dependencia, o sustituible por parámetro o subclases.

+0

¿Qué pasa si desarrollas tu código de prueba primero, en pasos de bebé? Regularmente deberá tratar con el código interno de una forma u otra ... –

3

No con Moq.

Pero puede utilizar el marco de Moles gratuito de MS para hacer tales cosas. Escribí sobre esto aquí: Mocking the Unmockable: Using Microsoft Moles with Gallio. (no se aplica solo a Gallio, sino que da una buena impresión general de lo que puedes hacer con Moles ...). La otra alternativa sería Typemock ...

HTH. Thomas

+0

+ para la descripción de las herramientas gratuitas –

+1

Incorrecta (al menos en 2016). Ver la respuesta de Daryn. – mhvelplund

+0

A partir de 2016, MS Moles ha sido reemplazado por MS Fakes, de acuerdo con http://wayback.archive.org/web/20160316031214/http://research.microsoft.com/en-us/projects/moles/. – clacke

0

Si necesita probar un montón de código que no puede cambiar, será mejor que vaya con MS Moles o TypeMock desde el principio.

Los frameworks de burla gratuitos como Moq solo le dan soporte en interfaces y métodos virtuales. No suena como si va a ir muy lejos con eso ...

Thomas

55

Puede métodos virtuales internos fácilmente simulados añadiendo lo siguiente a su AssemblyInfo.CS:

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

Si su montaje tiene un nombre, que tendrá que incluir la clave pública para DynamicProxyGenAssembly2 (Gracias a comentar por @bvgheluwe; fuente: Moq quickstart guide):

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

No entiendo por qué la respuesta aceptada dice que nunca debes hacerlo. ¿No es eso lo que haces cuando usas la técnica de inyección de dependencia 'Extraer e invalidar' (método de fábrica local) descrita por Roy Osherove en Chapter 3 of The Art Of Unit Testing?

+1

Eso me ayudó mucho. ¡Gracias! – Fabian

+9

Esta debería ser la respuesta aceptada. Es todo un debate sobre si burlarse de un método interno es lo correcto, sin embargo, si has decidido que eso es lo que quieres hacer, esta es la forma de lograrlo. – CraigTP

+2

Esto no va a funcionar. Necesitas una clave pública también. – max

22

Marcos el método como internal *protected* (también virtual por supuesto)

+2

omg, lo resolvió. – max

+0

Esto funciona, pero ¿puede decirnos por qué funciona? – MrLore

+1

@MrLore funciona porque "_protected_ internal" significa que una subclase puede acceder al método en _any_ assembly, y si lo marca como "virtual", entonces su subclase de burla puede proporcionar una implementación personalizada – andreister

Cuestiones relacionadas