Tip: Cómo establecer el valor de %PathToWebRoot%

En un post anterior hablaba sobre pruebas unitarias de la interfaz de usuario.

En ese post hablaba sobre cómo Team System deja grabar secuencias que realizar el usuario contra la interfaz web para después poder repetir las secuencias grabadas tantas veces como consideremos.

Una de las cosas que comentaba es cómo poder configurar la prueba para indicarle que queremos que se arranque un servidor web de desarrollo cuando ejecutemos la prueba.

En el ejemplo ruta que usaba en el ejemplo, empleaba %PathToWebRoot%.

Pero….¿ qué valor tiene %PathToWebRoot%?

Pues el que le indiquemos, porque desde las opciones de Visual Studio ( Tools>Options ), en Test Tools>TestExecution podemos especificar cuál es el directorio raíz de la aplicación web.

image

Pruebas unitarias: Capa de acceso a datos

En este post abordaremos cómo es posible hacer pruebas unitaria sobre la capa de acceso a datos, tanto del código .NET ( C#, VB.NET o el que sea ) que usamos para acceder a los datos,como de los procedimientos almacenados que puede tener nuestra base de datos.

El código empleado para acceder a la base de datos podría ser algo similar a este:

public List<CustomerEntity> GetList(string name)
{
    List<CustomerEntity> list = new List<CustomerEntity>();
    CustomerEntity customer;
    try
    {
        string connectionString = 
            ConfigurationManager.ConnectionStrings["Database"].ConnectionString;
        using (SqlConnection conn = new SqlConnection(connectionString))
        {
            conn.Open();
            string commandText = "dbo.GetCustomerList";
            using (SqlCommand command = new SqlCommand(commandText))
            {
                command.CommandText = commandText;
                command.CommandType = CommandType.StoredProcedure;
                command.Connection = conn;
                command.Parameters.AddWithValue("@Name", name);
                using (SqlDataReader dr = command.ExecuteReader())
                {
                    if (dr != null)
                    {
                        while (dr.Read())
                        {
                            customer = new CustomerEntity();
                            customer.Name = dr["Name"].ToString();
                            customer.Address = dr["Address"].ToString();
                            list.Add(customer);
                        }
                    }
                }
            }
        }
    }
    catch (SqlException ex)
    {
        // Logear error.
    }

    return list;
}

Para poder probar este método no necesitamos conocer nada que no hayamos visto hasta ahora. Simplemente tendremos que tener juegos de datos para hacer que las pruebas sean algo más reales y poder probar el código. Por ejemplo, en el caso anterior nos interesa que cuando llamemos al procedimiento almacenado éste devuelva datos.

Para poder realizar pruebas unitarias de los procedimientos almacenados la cosa cambia, ya que es necesario disponer y conocer Visual Studio Database Edition.

Esta versión de Visual Studio nos permite versionar el schema de base de datos como cualquier otro proyecto, permitiendo que todos los desarrolladores del equipo puedan disponer de la última versión de la base de datos en cualquier momento.

Tiene bastante características que simplificar el trabajo con base de datos en equipos de desarrollo pero en este post hablaremos sobre la característica de realizar pruebas unitarias sobre procedimientos almacenados.

Con Visual Studio Database Edition vamos a estar seguros de que todos los desarrolladores tendrán siempre la última versión de schema y podrán desplegarla en su entorno antes de ejecutar las pruebas, por lo que con más motivo, cuando probamos nuestros métodos de acceso a datos podremos optar por que nuestras pruebas unitarias puedan usar la base de datos.

Yo al menos es lo que hago. Para poder probar la capa de acceso a datos, los métodos C#, uso la base de datos, sus procedimientos y los datos que creo con los planes de generación de datos, simplificando bastante la implementación de las pruebas.

En las aplicaciones que desarrollo, al menos siempre implemento una prueba unitaria por cada método de acceso a datos y por cada procedimiento almacenado y cómo mínimo, en las pruebas busco cobertura, es decir, que todos nuestros procedimientos estén probados y que se pruebe el “100%” del contenido de los mismos.

Si tenemos este tipo de pruebas implementadas sobre todos los procedimientos almacenados y sobre todos los métodos de acceso a datos nos estaremos protegiendo contra sentencias mal construidas, sentencias sql que no devuelven todos los campos que se esperan, errores en el número de parámetros que se pasan a los procedimientos, cambios en la base de datos que hacen que dejen de funcionar algunas sentencias SQL etc….justamente los errores típicos que suelen ocurrir cuando hablamos de acceso a datos.

Como veremos a continuación las pruebas unitarias de procedimientos almacenados son muy similares al resto de pruebas.

Para crear las pruebas unitarias, desde la vista de schema que nos ofrece Visual Studio Database Edition, tendremos que seleccionar los procedimientos almacenados sobre los que queremos implementar las pruebas.

image

Del mismo modo que ocurre con el resto de pruebas, nos permitirá crear las pruebas en un proyecto nuevo o en un proyecto existente. Si elegimos un proyecto ya existente podremos meterlo dentro de una clase de pruebas que exista o crear una nueva clase de pruebas dentro del proyecto seleccionado.

Una vez creadas las pruebas, podremos ver el código de la mismas y modificarlas según nuestras necesidades. Si seleccionamos la clase de pruebas veremos una ventana como la que se muestra a continuación.

image

image

En el primer desplegable de la izquierda aparece el listado de todos las pruebas que están dentro de la clase.

En el segundo desplegable podremos ver el código de la prueba o añadir código que nos interese ejecutar antes  ( pre-test ) o después de la prueba ( post-test ). Algo similar la funcionalidad de los métodos de inicialización que vimos en los post anteriores.

En la parte inferior, aparece otro desplegable que nos permite configurar la condición que hace que el resultado de la prueba sea correcta.

Podemos añadir tantas condiciones como queramos, incluso no añadir ninguna condición. En este último caso la prueba siempre daría como resultado que todo ha ido bien, salvo que se genere una excepción.

Visual Studio Database Edition también nos permite establecer algunos parámetros de configuración antes de lanzar las pruebas unitarias.

Por ejemplo, permite indicar si hay que hacer un despliegue automático antes de ejecutar las pruebas. Estos provocará que la base de datos se cree de nuevo y la establezca en su estado inicial.

También podremos indicar, si queremos utilizar un plan de generación de datos para cargar la misma con información de ejemplo sobre la cuál ejecutar las pruebas.

image

Para aquellos que no lo conozcáis se pueden crear planes de generación de datos para cargar las tablas de la base de datos con datos de ejemplo y así hacer que nuestras pruebas sean algo más reales.

Los planes se crean sobre el proyecto de base de datos. Add>Data Generation Plan.

image

image

Pruebas unitarias: interfaz de usuario ASP.NET

Llega el momento de ver lo que nos ofrece Visual Studio para hacer las pruebas sobre la capa de interfaz, en este caso sobre una interfaz ASP.NET.

Probar el 100% de la funcionalidad de la interfaz de usuario de manera automatizada es complicado con las herramientas que disponemos y siempre va a quedar una parte que obligatoriamente tendremos que cubrir con pruebas funcionales. Aún así, todo lo que podemos automatizar será tiempo que nos ahorraremos.

En este tipo de pruebas sigo un enfoque de pruebas de cobertura.

Una prueba unitaria de cobertura es aquella cuyo único objetivo es cubrir la mayor parte posible de código, sin realmente comprobar si el resultado de la prueba es el esperado. Este tipo de pruebas nos protegen contra errores graves, como excepciones inesperadas en el código.

Aunque siempre que sea posible es conveniente realizar pruebas de funcionalidad (comprueba que realmente hace lo que tiene que hacer) en algunos escenarios, como el que nos ocupa podemos usar este enfoque de cobertura.

Visual Studio nos permite grabar secuencia completas contra la interfaz de usuario, con el objetivo de poder repetirlas tantas veces como queremos. Este tipo de pruebas las podemos crear desde el menú de “Test”, creando una prueba de tipo Web.

image

image

Una vez terminada la grabación dispondremos de las secuencias grabadas para poder repetirlas tantas veces como queremos.

Desde el menú horizontal que se muestra en la imagen Visual Studio nos permite extender la funcionalidad de la prueba que acabamos de grabar; asociarle un datasource, añadir más grabaciones, convertir la prueba en código etc…

image

Una de las propiedades que nos interesa establecer es que cuando se inicie la prueba se arranque la aplicación ASP.NET para que la prueba pueda realizarse. Sino realizamos este paso la prueba fallará porque no encontrará la aplicación que queremos probar.

Desde una de las opciones de menú horizontal (Parametrizar servidor Web ) podemos indicarle que queremos que se arranque un servidor web de desarrollo cuando ejecutemos la prueba.

image

 

 

También desde el mismo menú podremos convertir la grabación que hemos realizar el código, para tener algo similar al código que aparece a continuación. En algunas ocasiones nos puede interesar tener la prueba en código para poder personalizarla según nuestras necesidades, por ejemplo, para hacer algún cambio respecto lo grabado.

        [TestMethod]
        [UrlToTest("http://localhost:20970/Default.aspx")]
        [AspNetDevelopmentServerHost("%PathToWebRoot%\UTDemo\UTDemo", "/")]
        public override IEnumerator<WebTestRequest> GetRequestEnumerator()
        {
            // Initialize validation rules that apply to all requests in the WebTest
            if ((this.Context.ValidationLevel >= Microsoft.VisualStudio.TestTools.WebTesting.ValidationLevel.Low))
            {
                ValidateResponseUrl validationRule1 = new ValidateResponseUrl();
                this.ValidateResponse += new EventHandler<ValidationEventArgs>(validationRule1.Validate);
            }

            WebTestRequest request1 = new WebTestRequest("http://localhost:20970/Default.aspx");
            request1.ThinkTime = 5;
            ExtractHiddenFields extractionRule1 = new ExtractHiddenFields();
            extractionRule1.Required = true;
            extractionRule1.HtmlDecode = true;
            extractionRule1.ContextParameterName = "1";
            request1.ExtractValues += new EventHandler<ExtractionEventArgs>(extractionRule1.Extract);
            yield return request1;
            request1 = null;

            ........
            ........
 
Fijaros en los atributos UrlToTest y AspNetDevelopmentServerHost. A través de estos dos atributos se consigue que cuando ejecutemos la prueba se arranque un servidor web de desarrollo con la aplicación web a probar.
 
Del mismo modo también, desde el menú horizontal, podríamos configurar una origen de datos para la prueba web, para que ciertos valores de la misma se carguen desde un origen externo a la prueba.
 
Por ejemplo, si tenemos un formulario de alta, cuando hemos grabado la prueba habremos metido ciertos valores, que son los que se han grabado. Nos puede interesar repetir la secuencia grabada pero que los datos utilizados no sean los mismos. En este caso podremos usar el origen de datos para que almacene los diferentes datos que queremos usar en la prueba.

image

 

 

Y para los que estéis pensando si existe algo parecido para interfaces WinForm, la respuesta es no, al menos hasta la salida de Visual Studio 2010.

Para los que necesitéis probar aplicaciones WinForm y no podáis esperar, os recomiendo este post de Rodrigo Corral.

[Artalde.NET] Depuración avanzada con WinDbg

El próximo día 1 de abril, miércoles, será la siguiente charla de Artalde.

El lugar y hora será el mismo de siempre, de 19:00 a 21:00 en la universidad de Deusto.

Tendremos el honor de tener entre nosotros a Pablo Alvarez Doval, todo un crack en esta materia.

Este evento romperá ligeramente con la tendencia sobre las sesiones técnicas acerca de las ultimísimas tecnologías para centrarse en una faceta poco novedosa, pero de la que aún queda mucho por hablar: la depuración avanzada. 

Nos centraremos en el profiling de problemas de rendimiento y depuración avanzada con WinDbg. Partiendo de un repaso teórico sobre determinados aspectos vitales del framework .NET (principalmente la gestión de memoria y de concurrencia), se abordarán a continuación aspectos como el análisis del rendimiento, localización de puntos calientes, resolución de problemas esquivos (cuelgues, pérdidas, bloqueos, CTDs…) tanto en vivo como de modo postmortem (mediante el análisis de volcados de memoria, etc).

También se abordarán, durante el transcurso de la sesión, aspectos de portabilidad como la construcción de un servidor de símbolos sincronizados, la generación de volcados de memoria en nuestras aplicaciones, etc.

No olvidéis registraros si estáis interesados en acudir. Registro.

Si de la charla sale algún tipo de material los subiré para que os lo podáis descargar y antes de que lo preguntéis, todavía seguimos sin estar online….así que sólo los que podáis acudir a la universidad podréis presenciar el evento.

Pruebas unitarias: Orígenes de datos para alimentar las pruebas

En algunas ocasiones, para poder probar de forma completa un módulo es necesario probar muchas variantes en los parámetros de entrada.

Por ejemplo, si tenemos nuestra ya famoso método Sumar, con podría interesar probar el método con diferentes parámetros de entrada, para comprobar que realmente suma bien en todas las situaciones.

Una primera aproximación podría ser escribir tantas pruebas como necesitemos, cambiando en cada prueba los parámetros de entrada. Una solución poco adecuada.

La solución, más adecuada, cuando las N pruebas sólo cambian en los datos de entrada, es usar la característica que nos ofrece Visual Studio para generar una única prueba y cargar los diferentes escenarios de datos desde un origen de datos.

El proceso para configurar un origen de datos para una prueba es muy sencillo. Desde la ventana que muestra la lista de pruebas unitarias de la solución, seleccionaremos la prueba unitaria que nos interese.

Una vez seleccionada podremos ver sus propiedades. A través de la propiedad “Data Connection String” podremos especificar el origen de datos.

image

Si pinchamos sobre esta opción nos aparecerá un asistente que nos guiará paso a paso para especificar el origen de datos, que puede ser una base de datos, un fichero CSV o un fichero XML.

image

Seleccionamos un fichero CSV que tiene tres valores separados por comas. Los dos primeros son los valores a sumar, siendo el tercero el resultado esperado.

image

Una vez hecha esta operación, tendremos que modificar nuestra prueba para que sea capaz de usar el origen que acabamos de añadir.

A través de la variable de clase TestContext que posee la clase de pruebas podremos acceder a los datos, usando la propiedad DataRow.

La prueba unitaria queda de la siguiente manera:

[DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", 
    "|DataDirectory|\testdata.csv", "testdata#csv", DataAccessMethod.Sequential), 
    DeploymentItem("TestProject1\testdata.csv"), TestMethod()]
public void SumarTest()
{
    Service1 target = new Service1();
    int a = (int)this.TestContext.DataRow[0];
    int b = (int)this.TestContext.DataRow[1];
    int expected = (int)this.TestContext.DataRow[2];
    int actual;
    actual = target.Sumar(a, b);
    Assert.AreEqual(expected, actual);
}

Fijaros en los atributos DataSource y DeploymentItem. Estos dos atributos se han añadido al configurar el origen de datos.

El atributo DataSource indica el origen de datos que se empleará en la prueba, así como la forma de acceder al mismo.

El atributo DeployementItem permite especificar ficheros adicionales que se incluirán entre los ficheros que se usarán para la prueba. En este caso se indica que se va a incluir el fichero testdata.csv, que es el fichero que contiene todos los valores posibles que queremos probar como parámetros de entrada.

El resultado que obtenemos es como si la prueba la ejecutásemos tantas veces como número de registros tenga el origen de datos.

image

Pruebas unitarias: Probando el envío de correos electrónicos

Algo muy típico en todos los desarrollos es la necesidad de enviar correos electrónicos. En este post veremos cómo es posible probar de manera automatizada si nuestro método genera o no genera correos electrónicos.

En este caso vamos a simplificar y sólo vamos a probar un método que única y exclusivamente manda el correo. Nuestro método tendría el siguiente aspecto:

public static void SendMail(string from, string to, string subject, string body)
{
    MailMessage msg = new MailMessage(from, to, subject, body);
    SmtpClient sm = new SmtpClient();
    sm.Send(msg);
}

Nuestro objetivo será asegurarnos que cuando llamamos a este método se genera un mensaje de correo. Vamos a suponer que todos los parámetros que se reciben son correctos, por lo que no se realiza ninguna validación de los mismos.

La primera aproximación sería algo así.

[TestMethod()]
public void SendMailTest()
{
    string from = "admin@admin.com";
    string to = "target@sample.com";
    string subject = "subject";
    string body = "body";
    Class1.SendMail(from, to, subject, body);
}

 

El problema de esta aproximación, es que con esta prueba sólo podremos saber si la ejecución del método SendMail genera o no genera ninguna excepción, pero realmente no sabemos si se está enviando el mensaje.

Para poder comprobar realmente si el mensaje se envía necesitaríamos tener acceso al servidor SMTP o instalarlos uno en nuestro equipo para hacer las pruebas y poder acceder a él para comprobar si se ha enviado el mensaje…..la primera suele ser complicada por políticas de seguridad y la segunda me resulta un poco peñazo…

Como alternativa, el framework nos posibilita que podamos configurar el sistema de mensajería para que en lugar de usar un servidor SMTP para enviar los correos, simplemente éstos se dejen en disco, en un directorio. Para hacer pruebas unitarias esta característica resulta perfecta.

A través del fichero de configuración podremos indicar que los mensajes se dejen en disco:

<system.net>
  <mailSettings>
    <smtp deliveryMethod="SpecifiedPickupDirectory">
      <specifiedPickupDirectory pickupDirectoryLocation="c:MailMessages" />
      <network host="127.0.0.1" port="25"/>
    </smtp>
  </mailSettings>
</system.net>

 

 

Ten en cuenta que esta configuración la tienes que incluir en el fichero de configuración del proyecto de Test, ya que cuando se lanza la ejecución de las pruebas el fichero de configuración que se usa es el que está con el proyecto de Test.

Una vez que generamos el fichero a disco, ya podemos comprobar si éste se mandado realmente. Para ello añadiremos la siguiente línea a nuestra prueba unitaria:

Assert.AreEqual(expected,Directory.GetFiles(@"C:MailMessages","*.eml").Length);
 
En este caso sólo comprobamos que el fichero se haya generado pero podríamos hacer las comprobaciones que consideremos. Por ejemplo, abrir el fichero y comprobar si los datos del mismo coinciden con los parámetros que se le han pasado.

El fichero generado es un fichero de correo, con extension eml, que tiene el siguiente aspecto:

image

Ya por último, vamos a utilizar los métodos de inicialización para asegurarnos de que el entorno está como necesitamos antes de lanzar la prueba y que lo dejamos limpio después de finalizar la ejecución de las mismas.

  • [MyClassInitialize] Si no existe el directorio destino de los mensajes lo creamos. Si existe, nos aseguramos de que no tenga ficheros eml de ejecuciones anteriores.
  • [MyClassCleanup] Al finalizar las pruebas, eliminamos el directorio.
  • [MyTestCleanup] Después de la ejecución de cada prueba eliminamos el fichero eml que ha creado la prueba.
[ClassInitialize()]
public static void MyClassInitialize(TestContext testContext)
{
    if (Directory.Exists(@"C:MailMessages"))
        Directory.CreateDirectory(@"C:MailMessages");
    else
        DeleteMailMessages();
}

[ClassCleanup()]
public static void MyClassCleanup()
{
    if (Directory.Exists(@"C:MailMessages"))
        Directory.Delete(@"C:MailMessages", true);
}


[TestInitialize()]
public void MyTestInitialize()
{
}

[TestCleanup()]
public void MyTestCleanup()
{
    DeleteMailMessages();
}

private static void DeleteMailMessages()
{
    if (Directory.Exists(@"C:MailMessages"))
    {
        string[] files = Directory.GetFiles(@"C:MailMessages","*.eml");
        foreach ( string file in files )
            File.Delete(file);
    }
}

Pruebas unitarias: Servicios Web

Siguiendo con los post sobre pruebas unitarias, en éste intentaré explicar los recursos que nos ofrece el framework de Visual Studio para probar servicios web.

El primer paso será convertir nuestro método Sumar en un servicio web ASP.NET.

Como seguro que todos ya sabréis el proceso es muy sencillo. Sería crear un proyecto de tipo “ASP.NET Web Service Application” y decorar el método que queremos exponer con el atributo WebMethod.

[WebMethod]
public int Sumar(int a, int b)
{
    return a + b;
}

 

Una vez que tenemos el servicio web creado, desde el menú contextual crearemos el proyecto de Test y la prueba unitaria del método Sumar.

El código que nos genera Visual Studio es el siguiente:

[TestMethod()]
[HostType("ASP.NET")]
[AspNetDevelopmentServerHost("C:\WebService1\WebService1", "/")]
[UrlToTest("http://localhost:51038/")]
public void SumarTest()
{
    Service1 target = new Service1(); // TODO: Initialize to an appropriate value
    int a = 0; // TODO: Initialize to an appropriate value
    int b = 0; // TODO: Initialize to an appropriate value
    int expected = 0; // TODO: Initialize to an appropriate value
    int actual;
    actual = target.Sumar(a, b);
    Assert.AreEqual(expected, actual);
    Assert.Inconclusive("Verify the correctness of this test method.");
}

 

Como podéis ver, el código resultante es similar al que nos generó cuando el método Sumar no era un servicio web. En este caso ha añadido varios atributos al método, además del ya conocido TestMethod; HostType, AspNetDevelopmentServerHost y UrlToTest.

Pues bien, estos tres atributos nuevos no nos van a valer para mucho, ya que son atributos que se usan para probar interfaces ASP.NET pero no servicios web. Si ejecutásemos nuestra prueba unitaria fallaría y daría un error como este:

image

Si quitamos estos atributos el código resultante es el mismo que el que teníamos antes, cuando el método Sumar no era un servicio web. Y esto tiene su lógica, ya que un servicio web ASP.NET no es más que una clase normal y corriente en la cuál decoramos sus métodos con el atributo WebMethod.

Por lo tanto, probar la lógica que pueda incluir un servicio web sería como probar cualquier otra clase y no tendrá ninguna otra peculiaridad….o sí?

[TestMethod()]
public void SumarTest()
{
    Service1 target = new Service1();
    int a = 1;
    int b = 1;
    int expected = 2;
    int actual;
    actual = target.Sumar(a, b);
    Assert.AreEqual(expected, actual);
}

Pues sí, tiene una peculiaridad. Los clientes reales no acceden al servicio web como una clase normal, sino que acceden a ella a través de una clase proxy que se genera previamente. ( Add Web Reference o Add Service Reference ).

Por lo tanto, al menos una de las pruebas que implementemos sobre el servicio web debe simular ser un cliente real y hacer las llamadas a través de una clase proxy, para comprobar de esta manera que el servicio web se podrá exponer correctamente y que los clientes podrán llamarlo.

En el proyecto de Test tendremos que añadir una referencia web ( Add Web Reference ) al servicio web ASP.NET que queremos probar.

Una vez que tenemos la referencia, en lugar de llamar directamente a la clase, usaremos la clase proxy que se ha generado al añadir la referencia web.

Pero claro, si queremos acceder al servicio web a través del proxy, necesitaremos que el servicio se arranque cada vez que lanzamos la prueba. Si ejecutamos la prueba y el servicio no está arrancado, ésta fallará, ya que lógicamente no podrá llamarlo.

image

Para conseguir que el servicio web se arranque al ejecutar la prueba tendremos que usar el atributo AspNetDevelopmentServer y el método TryUrlRedirection.

[TestMethod()]
[AspNetDevelopmentServer("MiServicio","C:\WebService1\WebService1")]
public void SumarTest()
{
    MiServicio.Service1 target = new MiServicio.Service1();

    Assert.IsTrue(
        WebServiceHelper.TryUrlRedirection(target, testContextInstance, "MiServicio"),
        "Web Service Redirection Failed"
        );
    int a = 1;
    int b = 1;
    int expected = 2;
    int actual;
    actual = target.Sumar(a, b);
    Assert.AreEqual(expected, actual);
}

AspNetDevelopmentServer permite que creemos un servidor de desarrollo para el servicio, servidor que se arrancará en el momento que ejecutemos la prueba. Este servidor será temporal y finalizará al terminar la prueba. El servidor que se crea establece el puerto de escucha de forma dinámica lo que podría hacer que la prueba fallase, al no coincidir la URL que se ha creado en el servidor con la URL que está establecida en el fichero de configuración. Para hacer que la URL que se crea coincida con la que tenemos configurada se usa el método TryUrlRedirection.

TryUrlRedirecion es un método estático de la clase WebServiceHelper que devuelve un valor booleano si se ha podido ejecutar la redirección. Esté método recibe como primer parámetro el objeto del servicio web que vamos a redirigir.

Si utilizáis Visual Studio 2008 al añadir la referencia al servicio web también podéis usar “Add Service Reference” para que sea compatible con los servicios WCF. Si en lugar de estar probando un servicio web ASP.NET estáis probando un servicio WCF esta sería la única opción.

En este caso, si usáis la opción “Add Service Reference” notaréis que si intentáis usar el método TryUrlRedirection os dará un error de tipo en los parámetros, ya que este método no se puede usar con las clases proxy generadas de esta manera.

La solución es implementar nuestro propio método TryUrlRedirection, tal y como podemos ver en el siguiente código.

public bool TryUrlRedirection(object client, TestContext context, string identifier)
{
    bool result = true;
    try
    {
        PropertyInfo property = client.GetType().GetProperty("Endpoint");
        string webServer = context.Properties[
            string.Format("AspNetDevelopmentServer.{0}", identifier)].ToString();
        Uri webServerUri = new Uri(webServer);
        ServiceEndpoint endpoint = (ServiceEndpoint)property.GetValue(client, null);
        string serviceAddress = endpoint.Address.Uri.OriginalString;
        serviceAddress = serviceAddress.Replace(
            endpoint.Address.Uri.Authority, webServerUri.Authority);
        endpoint.Address = new EndpointAddress(serviceAddress);
    }
    catch (Exception)
    {
        result = false;
    }
    return result;
}

Para los que uséis servicio WCF lo único que hay que tener en cuenta es que si el proyecto dónde se alberga el servicio es una librería de servicios WCF no será necesario realizar ninguna acción adicional para conseguir que el servicio esté a la escucha en el momento de ejecutar la prueba. Este tipo de proyectos hace uso del host de servicio de WCF (WcfSvcHost) para poder hospedar de manera automática el servicio.

Si el servicio está en un proyecto web de WCF este proceso no se realizará de manera automática y habrá que realizar los mismo que para probar servicios web ASP.NET.