2010-05-18 11 views
6

Tengo lo que podría ser visto como un híbrido extraño de IQueryable<T> y IList<T> colecciones de objetos de dominio pasados ​​por mi pila de aplicaciones. Intento mantener la mayor cantidad posible de "consultas tardías" o "carga lenta". Hago esto de dos maneras:¿Cómo puedo simular o probar mi funcionalidad de evaluación/ejecución diferida?

  1. Mediante el uso de una capa de datos LinqToSql y pasando IQueryable<T> s a través de repositorios y para mi capa de aplicación.
  2. Luego, después de que mi capa de aplicación pase IList<T> s, pero donde ciertos elementos en el gráfico de objeto/agregado son 'chained' with delegates para diferir su carga. A veces, incluso el contenido del delegado depende de las fuentes IQueryable<T> y se inyecta el DataContext.

Esto funciona para mí hasta ahora.

Lo que es extremadamente difícil es probar que este diseño realmente funciona. Es decir. Si derroto a la parte "floja" en alguna parte y mi evaluación/ejecución ocurre temprano, entonces todo es una pérdida de tiempo. Me gustaría poder TDD de alguna manera.

No sé mucho acerca de los delegados o la seguridad de la secuencia, ya que se aplica a los delegados que actúan en la misma fuente. Me gustaría poder burlarme del DataContext y rastrear de alguna manera ambos métodos de aplazamiento (el SQL IQueryable<T> y los delegados) la carga para que pueda tener pruebas que demuestren que ambas funciones funcionan en diferentes niveles/capas de la aplicación /apilar.

Como es crucial que la postergación funcione para que el diseño sea de algún valor, me gustaría ver que las pruebas fallen cuando rompo el diseño en un nivel dado (separado de la implementación en vivo). es posible?

Respuesta

4

En morelinq, tenemos una llamada "secuencia de interrupción" para probar eso. Básicamente, es un enumerador que emitirá una excepción cada vez que se enumere.

Puede ser tan fácil como:

internal sealed class BreakingSequence<T> : IEnumerable<T> 
{ 
    public IEnumerator<T> GetEnumerator() 
    { 
     throw new InvalidOperationException(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

Una prueba para la que se ve así:

[Test] 
    public void XyzIsLazy() 
    { 
     var source = BreakingSequence<EntityClass>().AsQueryable(); 

     // inject it as your query source wherever appropriate 
     var query = source.Where(x=> true); 
     // does not throw, where does not enumerate the sequence 
    } 
+0

Parece un comienzo. ¿Qué tal si tengo como 'LazyItem ' que usa delegados para activar la evaluación del elemento encapsulado? http: // stackoverflow.com/questions/1669607/is-this-repository-pattern-efficient-with-linq-to-sql/1695561 # 1695561 –

+0

@cottsak: Puede establecer que el delegado sea un delegado de interrupción (un delegado que genera una excepción). –

+0

Suena como una buena idea. Tal vez estaba buscando una solución más compleja cuando no era necesario. –

2

Voy a responder de un modo similar a lo que respondió Johannes Rudolph. Parece que estás pensando lo correcto, queriendo tener una prueba para algo importante que sería difícil rastrear si falla.

Definitivamente, recomendaría utilizar un simulacro para este fin. Johannes sugirió un objeto que arroja una excepción cuando se enumera. Dado que su objeto está modelado, creo que debería poder usar cualquier objeto que desee. Un marco de burla, como Rhino.Mocks (gratuito) o TypeMock Isolator (caro), puede ser muy útil. Recomiendo encarecidamente buscar marcos de burla si no lo has hecho ya.

Con un simulacro en la mano, puede evaluar que las operaciones se realicen en un orden determinado cuando ejecute determinado código de prueba. Puede programar su simulación para registrar qué operaciones se llevan a cabo y luego verificar la grabación al final de la prueba.

+0

+1 para la sugerencia de grabación. He usado burlas muy a la ligera. He visto los patrones de "grabación" y esa podría ser una gran manera de reunir una cadena completa de operaciones complejas en una prueba. Gracias. –

+0

Sí evalué TypeMock Isolator, pero decidí que es muy costoso de usar para las pocas pruebas que hago. Sin embargo, si va a probar muchas cosas como esta, puede descubrir que a menudo hace que configurar sus pruebas sea mucho más fácil de lo que sería con las otras estructuras. –

+0

Sí, sé que Rhino Mocks graba, pero Moq sugiere que "grabar" no es tan bueno y está diseñado para no seguir este enfoque, así que tal vez veremos cómo Moq podría satisfacer lo anterior. Tal vez eso arrojará algo de inspiración sobre cómo probar esto. –

Cuestiones relacionadas