CollectionAssert.AreEqual vs CollectionAssert.AreEquivalent

Como parte de mi trabajo diario tengo que hacer bastantes tests unitarios. Por esta razón me he ido familiarizando con las distintas clases que el framework de testeo de Visual Studio nos ofrece al respecto.

Una de las últimas que descubrí pero, por otra parte, de las más útiles, es CollectionAssert. Esta clase permite realizar aserciones sobre colecciones y listas, como su propio nombre indica.

Dos son los métodos que más frecuentemente utilizo, pero cuya semántica es lo bastante parecida como para merecer una explicación un poco más detallada:

  • AreEqual: este método compara dos colecciones y se asegura de ambas tienen los mismos elementos, en el mismo orden y la misma cantidad.
  • AreEquivalente: este método, sin embargo, simplemente comprueba que ambas colecciones tengan los mismos elementos y en la misma cantidad, sin importar el orden en que se encuentren.

Por lo tanto, AreEqual no es más que una versión más restricctiva de AreEquivalent, útil si queremos hacer una aserción más precisa en nuestras pruebas.

Filtrar generación en Moles

Últimamente me he tenido que pelear un poco con Moles. Para los que no sepan qué es Moles, pueden consultar este post mío de hace un tiempo (ya me parezco a Enrique Dans autocitándome). Para los perezosos, resumir en que es un framework para testing que permite inyectar código en cualquier llamada al framework .NET. El ejemplo que suele verse en la mayoría de vídeos y textos demuestra cómo se puede “configurar” lo que queremos que devuelva DataTime.UtcNow, algo que sin Moles resulta imposible, pues UtcNow no tiene método set.

Bien, si en una librería que estás intentando “molear” tienes un tipo rebelde que se te rompe la generación, o bien prefieres limitar el número de clases que se molean a sólo aquellas que van a utilizar, esto te puede ser de utilidad. En cada mole tendremos un fichero XXX.moles, donde XXX es el ensamblado que hemos moleado. En dicho fichero podemos configurar algunas de las características del mole, lo que hará que se vuelva a generar teniendo en cuenta nuestra configuración.

Si quisiéramos evitar que se generara código para la clase DateTime en el ensamblado System, deberíamos añadir algo parecido a esto en nuestro fichero .moles:

<Moles xmlns="http://schemas.microsoft.com/moles/2010/">
  <Assembly Name="System" />
  <CodeStyle DisableUniqueAlias="true" />
  <StubGeneration>
    <Types>
      <Remove Namespace="System" TypeName="DateTime" />
    </Types>
  </StubGeneration>
  <MoleGeneration>
    <Types>
      <Remove Namespace="System" TypeName="DateTime" />
    </Types>
  </MoleGeneration>
</Moles>

El fragmento es bastante autoexplicativo: le estamos indicando que, tanto de la generación de Stubs como de Moles, nos elimine la clase DateTime dentro del espacio de nombres System. Podremos introducir tantas entradas dentro de las etiquetas Types, como tipos queramos evitar “molear”.

 

Visto en los Foros de social.msdn.microsoft.com

Atributo InternalsVisibleTo

El atributo InternalsVisibleTo puede resultarnos muy útil en situaciones en las que tengamos la necesidad de acceder, desde un ensamblado, a los miembros Internal de las clases de otro ensamblado.

Un ejemplo que me he encontrado últimamente de su uso es en el testeo de aplicaciones Silverlight. Por desgracia, Silverlight no tiene ningún framework de testeo que sea capaz de generar accessors, probablemente porque Reflection no funciona para campos privados en Silverlight.

Para sustituir esta carencia, en algunos casos podremos marcar la visibilidad de miembros que queramos testear como Internal en lugar de Private y, haciendo uso de InternalsVisibleTo, acceder a ellos desde los correspondientes tests. ¿Cómo lo lograríamos? Son unos pocos pasos:

Primer paso: obtener la clave pública

Necesitamos conocer la clave pública de firmado del ensamblado al que queremos conceder el privilegio de poder acceder a los miembros internal. Para ello, en una consola de Visual Studio, deberemos introducir el siguiente comando:

sn -Tp c:UsersjavierprojectsMyProjectDllToGrantAccessToInternals.dll

De la salida que nos genera este comando, nos la copiamos para hacer el siguiente paso.

Segundo paso: definir el atributo

Ahora que ya conocemos la PublicKey del ensamblado (no confudir con la PublicKeyToken que aparece en los qualified names), necesitamos definir el atributo en el fichero AssemblyInfo del proyecto. En dicho fichero deberemos añadir algo como lo siguiente:

[assembly: InternalsVisibleTo("DllToGrantAccessToInternals.dll, PublicKey=0024000004…)]

 

¿Sencillo no? Con esto ya podríamos ver los miembros Internal del ensamblado en que hemos definido el atributo, desde el ensamblado DllToGrantAccessToInternals.

Petición POST con C#

Dicen que nunca te acostarás sin aprender algo nuevo. Yo he tenido mi ración diaria con la forma de realizar una petición POST desde .NET. Probablemente sea una simpleza que todo el mundo sabe, pero yo lo desconocía.

El proceso es bastante intuitivo, salvo en la forma de añadir parámetros a la petición, que a mí me ha dejado algo más sorprendido. Pasos:

  1. Instanciar una URI con la dirección a la que se quiere hacer la petición, pero sin parámetros.
  2. Crear el objeto Request. Castearlo directamente a HttpWebRequest, puesto que el Create, aunque devuelva un WebRequest, en realidad es un objeto HttpWebRequest (que es un subtitpo de WebRequest).
  3. Configurar la request, indicando que se va a usar POST (obligatorio), el content-type (opcional), la longitud (obligatorio) y la versión del protocolo HTTP (opcional).
  4. Obtener un steam de la petición. Se va a añadir los parámetros como si fueran bytes, que al fin de cuentas es el contenido de la petición.
  5. Terminamos haciendo una llamada a GetResponse para obtener la respuesta.

El código de todo este proceso sería algo parecido a lo siguiente:

   1: HttpWebRequest httpRequest = 
   2:     HttpWebRequest.Create("http://direccion.com/pagina") as HttpWebRequest;            
   3: httpRequest.Method = "POST";
   4: httpRequest.ProtocolVersion = HttpVersion.Version11;
   5: // Parameters es un string que contiene todos los parametros en 
   6: // formato param1=value&param2=&param3=value
   7: httpRequest.ContentLength = Encoding.ASCII.GetByteCount(parameters);
   8: httpRequest.ContentType = "application/x-www-form-urlencoded";            
   9:  
  10: using (Stream requestStream = httpRequest.GetRequestStream())
  11: {
  12:     byte[] parametersBuffer = Encoding.ASCII.GetBytes(parameters);
  13:     requestStream.Write(parametersBuffer, 0, parametersBuffer.Length);
  14: }
  15: WebResponse httpResponse = httpRequest.GetResponse();