Enlaces e información
Comenta lo que creas oportuno.
- Otros posts
- Agilizando el desarrollo
- Cosas con las que estoy…
Mockeando…
Tiene un nombre curioso y curioso es su funcionamiento y utilidad.
Muchas veces tenemos que testear una funcionalidad (Unit Testing) pero nos encontramos con dificultades al darnos cuenta de que la funcionalidad a testear depende mucho de factores externos: Bases de datos, ficheros, etc. Un principio básico del testeo dentro de la filosofía TDD (Test-Drivent Developement) es el del testeo aislado del resto: Si vamos a testear una funcionalidad, debemos asegurarnos de que nada interfiere en dicha funcionalidad y de que los resultados nos van a decir si hemos implementado bien o mal dicha funcionalidad y no otro artefacto relacionado o no con ella.
Para poder implementar esta premisa, existen los Mocks, cuya traducción es mofa, lo cual me hace pensar que puede ser una buena definición de los mismos: El código que vamos a testear utiliza un sistema externo pero en vez de que utilice dicho sistema externo le vamos a hacer utilizar una mofa del mismo, una mala copia.
Existe por la red una librería de clases que permite implementar mocks para testear: nMock dicha librería proporciona un mecanismo que genera objetos que cumplen cierto interfaz en tiempo de ejecución.
Supongamos que tenemos un interfaz como el siguiente:
1 Public Interface IProcesoExterno
2 Function Llamada(ByVal strValor As String) As Integer
3 End Interface
Y una clase que accede a un objeto que implementa este interface:
1 Public Class CClaseATestear
2 Public m_objProcExterno As IProcesoExterno
3
4 Public Sub New(ByVal objProcExterno As IProcesoExterno)
5 m_objProcExterno = objProcExterno
6 End Sub
7
8 Public Function FuncionATestear(ByVal strValor As String) As Integer
9 Return m_objProcExterno.Llamada(strValor)
10 End Function
11 End Class
Como se puede ver, la funcion a testear (en la linea 9 llamada, de manera original, FuncionATestear) llama a una de las funciones implementadas por el Interfaz. Queremos testear esa funcion, pero no queremos que se acceda al sistema externo que implemenat el interfaz. Para ello creamos un objeto mock que implementa la interfaz. Nuestra clase de testeo podría ser la siguiente:
1 <NUnit.Framework.TestFixture()> _
2 Class CClaseTesteadora
3
4 Protected m_objMockControl As NMock.DynamicMock
5
6 <NUnit.Framework.SetUp()> _
7 Public Sub SetUp()
8 m_objMockControl = New NMock.DynamicMock(GetType(IProcesoExterno))
9 End Sub
10
11 <NUnit.Framework.TearDown()> _
12 Public Sub TearDown()
13 m_objMockControl.Verify()
14 End Sub
15
16 <NUnit.Framework.Test()> _
17 Public Sub TestearFuncion()
18 Dim objClaseATestear As CClaseATestear
19 Dim iRet As Integer
20
21 ‘ Pasar el interfaz "mockeado" a la clase
22 objClaseATestear = New CClaseATestear(m_objMockControl.MockInstance)
23
24 ‘ Establecer el resultado de la funcion implementada por el interfaz
25 m_objMockControl.SetupResult("Llamada", 10, GetType(String))
26
27 ‘ Llamar a la funcion a testear
28 iRet = objClaseATestear.FuncionATestear("")
29
30 ‘ Comprobar que el resultado es correcto
31 NUnit.Framework.Assert.AreEqual(iRet, 10)
32 End Sub
33 End Class
Linea 8: Lo primero es, que en la inicialización de la clase de testeo, creamos un DynamicMock partiendo de la definición del interfaz.
Linea 22: Cuando creamos un objeto de la clase a testear, le pasamos una instancia del DynamicMock creado.
Linea 25: Definimos el comportamiento que tendrá la funcion de la interface. Estamos definiendo un comportamiento de una instancia de un objeto definido por un interfaz, que en realidad no existe. De alguna manera estamos engañando a la clase a testear. Lo bueno es que podemos definir que es lo que devuelve dicha funcion "engañosa".
Linea 31: Testeamos que la funcion devuelve lo que queremos. He simplificado mucho el codigo, para que sea muy entendible. Esta claro que no vamos a testear directamente lo que nos devuelva la funcion "mockeada", pero seguramente el resultado a testear depende mucho del comportamiento de la funcion "engañosa" utilizada.
Con todo esto podemos definir unas pruebas de testeo y controlar que, independientemente, de los agentes externos, nuestro código se comporta de la manera esperada. Que es el objetivo de las pruebas de testo unitarias.
Y esto solo es el principio….