2009-12-21 27 views
5

Soy nuevo en Mocking y estoy un tanto familiarizado con las pruebas unitarias y finalmente he decidido abordar el nuevo proyecto desde el principio con un estricto enfoque TDD. Sin embargo, tengo una clase de servicio y un método al que necesito agregar pruebas retrospectivamente, ya que se ha promocionado a partir de un prototipo.Servicio de prueba unitaria que tiene llamada WCF (MSUnit + Moq)

No sé por dónde empezar, aunque en esta prueba en particular, se trata de las clases y métodos involucrados:

public class PageService : IPageService 
{ 
    private readonly ITestService testServiceClient; 

    public PageService(ITestService testServiceClient) 
    { 
     this.testServiceClient = testServiceClient; 
    } 

    public Page GetPage(Guid websiteId, string pageKey) 
    { 
     Page builtPage = null; 

     // WCF SERVICE CALL I DO NOT WANT EXECUTING WHEN RUNNING UNIT TEST 
     // BUT RATHER WANT A BLANK NEW INSTANCE OF "PAGE" CREATED USING MOQ?? 
     var page = testServiceClient.GetPage(websiteId, pageKey); 

     if (page == null) 
      return null; 

     builtPage = new Page(); 

     [code here to build builtPage if input params ok] ... 

     return builtPage; 
    } 
} 

Lo que estoy esforzándome por hacer, es escribir un ensayo, de esta espero poder ampliar todas las permutaciones de las pruebas GetPage(...), pero para la primera prueba simplemente si se ha pasado un websiteId y pageKey válidos, si es así, recibe un ejemplar válido de Page y afirma verdadero para la prueba unitaria.

testServiceClient es un cliente de servicios de WCF, esto fue envuelto en un comunicado using() antes, pero se han trasladado fuera de que, en la esperanza para ponerlo en marcha con la inyección de dependencia ya que siento que será el primer paso necesario para la prueba, por lo que entiendo, tendré que darle una falsa/burla? wcf client en cambio, ¿dónde devuelve testServiceClient.GetPage() un conjunto de datos en memoria conocido? Espero estar en el camino correcto allí.

Así que aquí está mi planos iniciales de mi unidad de prueba (estoy usando marco Moq, Setup() es la nueva versión del Expect() si no ha utilizado el último Ver de Moq):

/// <summary> 
/// Tests service returns a valid instance of type `Page` when a valid website and valid page key is tested. 
/// </summary> 
[TestMethod] 
public void Test_Valid_Website_And_Valid_PageKey_Returns_Valid_Instance_Of_Page() 
{ 
    // Arrange 
    Page page = null; 

    // Act 
    var newPage = new Page() { Title = "Mocked Version!?"}; 

    testServiceClient = new Mock<ITestService>(); 
    testServiceClient.Setup(x => x.GetPage(websiteId, "about-us")).Returns(newPage); 

    service = new PageService(testServiceClient.Object); 
    page = service.GetPage(websiteId, "about-us"); 

    // Assert 
    Assert.IsInstanceOfType(page, typeof(Page), "Object was not of expected instance type."); 
} 

que no tengo idea de dónde ir desde aquí, o si estoy en el camino correcto? Puedo confirmar lo anterior no tiene errores de sintaxis, y yo recibir una excepción:

System.ArgumentException: Invalid setup on a non-overridable member: 
x => x.GetPage(websiteId, "about-us"). 

único que sé es que quiero que mi service.GetPage(...) a devolver una nueva instancia, como websiteId y pageKey era válida, sin embargo yo no' Quiero que use la verdadera llamada de WCF testServiceClient.GetPage() ... espero entender la idea de burlarme correctamente. ¿Lo he dicho correctamente a través de Moq cuando usa testServiceClient.GetPage en ese servicio, realmente solo devuelve una nueva instancia de página?

¡Cualquier aclaración es muy apreciada! ¡Gracias chicos!

Respuesta

4

Yo diría que estás en el camino correcto. Si ITestService es realmente una interfaz (como lo indica su nombre), podrá simularlo.

Sin embargo, cuando defina sus Configuraciones, Moq debe ser capaz de identificar qué método quiere decir, y parece que de alguna manera indica un método que no existe en la interfaz.

No nos mostró la interfaz ITestService, y tampoco conocemos el tipo de la variable websiteId.

Si observa detenidamente el método de instalación, verá que en realidad es un método genérico, por lo que las inferencias de tipo se realizan cuando lo llama sin los parámetros genéricos.

Supongo que la declaración de websiteId de alguna manera choca con la declaración de GetPage.Si, por ejemplo, websiteId fue declarado como object, Moq se ocuparía de un método con esta firma:

Page GetPage(object x, string y); 

que no es lo mismo que

Page GetPage(Guid x, string y); 

En cualquier caso, una vez que logras hacer que la configuración funcione, su idea básica sobre la prueba de la unidad parece estar bien. Se puede hacer algo más que afirmar que la instancia no es nulo, debido a que el simulacro se asegurará de que la instancia devuelta es la misma que la instancia que Originall configurar:

[TestMethod] 
public void Test_Valid_Website_And_Valid_PageKey_Returns_Valid_Instance_Of_Page() 
{ 
    // Arrange 
    Page page = null; 

    // Act 
    var newPage = new Page() { Title = "Mocked Version!?"}; 

    testServiceClient = new Mock<ITestService>(); 
    testServiceClient.Setup(x => x.GetPage(websiteId, "about-us")).Returns(newPage); 

    service = new PageService(testServiceClient.Object); 
    page = service.GetPage(websiteId, "about-us"); 

    // Assert 
    Assert.AreEqual(newPage, page); 
} 

Aviso la aserción mucho más valioso.

+0

+1 Buena respuesta - @GONeale, solo para confirmar lo que dice Mark, he realizado una prueba rápida con MOQ y una interfaz que devuelve una página: funciona bien. Parecería que estás haciendo algo así como burlar una instancia concreta donde GetPage no se declara virtual. –

+0

Hola muchachos, gracias por tomarse el tiempo para leer mi publicación. Well ITestService es un WCF Generated Service Client (el proyecto de clic derecho -> agregar la referencia del servicio). A la luz de esto, no creo que pueda declararlo como 'virtual' ya que es una clase generada automáticamente. Sin embargo, podría crear una clase simple de llamadores de WCF y hacer esto virtual, ¿eso te ayudaría a pensar? Gracias por el consejo de Assert. – GONeale

+0

¿Entiendo correctamente al decir al declarar 'testServiceClient.Setup (x => x.GetPage (..)). Returns (newPage)' indica cualquier llamada a un nombre de ese método (anidado incluso como el método de un objeto pasado a través de como un parámetro como el ejemplo de 'new PageService (testServiceClient.Object)') para no ejecutar realmente el método * actual * (wcf), sino simplemente devolver una instancia 'newPage' en su lugar. ¿Es por eso que se requiere 'virtual', lo reemplaza con contenidos de método totalmente nuevos? – GONeale

Cuestiones relacionadas