2010-02-11 15 views
30

Estoy creando un repositorio que expone IQueryable. ¿Cuál es la mejor manera de burlar esto para mi prueba unitaria?¿Cómo me burlo de IQueryable? <T>

Desde que estoy usando RhinoMocks para el resto de mis objetos simulados, he tratado de hacer lo siguiente:

IQueryable<MyObject> QueryObject = 
    MockRepository.GenerateStub<IQueryable<MyObject>>(); 

Esto no funciona, entonces he intentado hacer esto:

IQueryable<MyObject> QueryObject = 
    (new List<MyObject> { new MyObject() }).AsQueryable(); 

¿Hay una mejor manera de hacerlo, o tiene algún otro soporte de frameworks burlones para IQueryable?

Mi interfaz de repositorio es el siguiente:

public interface IRepository<T> where T : TableServiceEntity 
{ 
    IQueryable<T> Table { get; } 
    void Attach(T existingItem); 
    void Delete(T itemToDelete); 
    void Insert(T newItem); 
    T Load(string partitionKey, string rowKey); 
    IEnumerable<T> Load(string partitionKey); 
    IEnumerable<T> Query(IQueryable<T> query); 
    IEnumerable<T> Last(int count); 
    T Last(); 
    void Update(T item); 
} 

Aquí es el método que yo quiero hacer la prueba:

public Post LoadPost(int year, int month, int day, string slug) 
{ 
    var query = from p in _blogRepository.Table 
       where 
        p.PartitionKey == Key.Partition(year, month, day) 
        && p.Slug == slug 
       select p; 

    var posts = _blogRepository.Query(query.Take(1)); 

    return posts.First(); 
} 

entonces aquí está la prueba como lo tengo ahora mismo que probar LoadPost .

[Fact] 
public void LoadWillRetrieveByPartitionKeyAndRowKeyWhenUsingUriFormat() 
{ 
    Repository 
     .Stub(x => x.Query(Arg<IQueryable<Post>>.Is.Anything)) 
     .Return(new List<Post> {_post}); 

    var result = Service.LoadPost(
          _post.Year(), 
          _post.Month(), 
          _post.Day(), 
          _post.Slug); 

    Assert.NotNull(result); 
} 

El código se toma de mi proyecto AzureBlog.

+0

¿Podría pegar su prueba? – Grzenio

Respuesta

8

que suele hacer exactamente lo que terminó haciendo en su prueba. Al escribir mis pruebas, supongo que las clases de la biblioteca .Net funcionan correctamente y no contienen errores, por lo que puedo usarlas en las pruebas. Cuando necesito una lista de prueba, colección, consultable, diccionario, etc. Simplemente creo la información real y la llevo con datos de prueba. Hace las pruebas mucho más legibles y rápidas de escribir, y para ser sincero, el riesgo es inexistente.

3

Si quiere simular su repositorio, no se burlará de IQueryable. En su lugar, haga una burla de los métodos de su repositorio para devolver valores conocidos fijos (como su segundo ejemplo) que pueden usarse para ejecutar sus pruebas unitarias.

+0

Empecé por esa ruta y luego terminé creando una capa adicional de un repositorio específico sobre un repositorio genérico. Esto dio como resultado mi Servicio de dominio -> Repositorio de dominio -> Repositorio genérico. Si puedo ir desde el Servicio de dominio -> Repositorio genérico y todavía puedo probarlo sin que se filtren detalles de implementación en el Servicio de dominio, sería mucho más feliz ya que es necesario mantener y probar menos códigos. –

+0

Veo lo que dices. Pero si su pregunta surgió al escribir pruebas unitarias para su DomainService, entonces creo que debería burlarse del DomainRepository y no preocuparse por el Repositorio genérico (por ahora). La prueba unitaria de DomainService se logra mejor burlándose de sus dependencias. En cuanto a DomainService, no debería importar cómo se implemente DomainRepository (es decir, heredar de una clase base). ¡Espero que esto ayude! – PatrickSteele

0

No estoy seguro si esto te ayudará ... pero hice algo como lo que estás hablando. En mi caso, tenía una clase de contexto de datos que usaba el repositorio.

Empecé creando una interfaz (IRepository) que incluía el método IQueryable. Luego creé dos clases que implementan esta interfaz. Una clase usa un ORM para la manipulación de datos (DbEntityRepository) y otra clase usa una propiedad de clase (MemoryRepository). La clase de contexto de datos tenía un constructor que requería el IRepository. Al hacer esto, podría usar el MemoryRepository para cuando se prueba el contexto de datos y podría usar el DbEntityRepository para la aplicación.

Si está interesado ... se puede encontrar el código en CodePlex: IQToolkitContrib

2

Sé que esta es una vieja pregunta, pero solo quiero agregar mis 2 centavos.

Tuve el mismo problema con los repositorios generados con SharpLite, que es un framework ASP .NET MVC que uso de vez en cuando. Después de un tiempo, encontré una solución, el único problema es que está usando Moq, y no Rhino Mocks, pero posiblemente pueda encontrar una forma de adaptarlo. Hice un blog post here sobre cómo hacerlo.

Básicamente se trata de crear una lista que implemente IQueryable y la utilice como fondo de datos falsos. Espero poder ayudar!

Cuestiones relacionadas