2011-09-14 10 views
10

Siguiendo es mi genérico interfaz de repositorio de base deMoq Parámetros TargetParameterCountException: Parámetro recuento desajuste Excepción

public interface IRepository<T> 
{ 
    IQueryable<T> AllIncluding(params Expression<Func<T, 
           object>>[] includeProperties); 
} 

mi entidad

public class Sdk 
{ 
    public Sdk() 
    { 
     this.Identifier = Guid.NewGuid().ToString(); 
    } 

    public virtual ICollection<Resource> AccessibleResources { get; set; } 

    public string Identifier { get; set; }  
} 

y siguiendo es el repositorio específico

public interface ISdkRepository : IRepository<Sdk> 
{ 
} 

ahora estoy tratando de probar un controlador, usando moq

siguiente es el código que estoy tratando de probar

public ActionResult GetResources(string clientId) { 
     var sdkObject = sdkRepository 
          .AllIncluding(k => k.AccessibleResources) 
          .SingleOrDefault(k => k.Identifier == clientId); 
     if (sdkObject == null) 
      throw new ApplicationException("Sdk Not Found"); 
     return Json(sdkObject.AccessibleResources.ToList()); 
    } 

utilizando la prueba siguiente

[Test] 
public void Can_Get_GetResources() 
{ 
    var cid = Guid.NewGuid().ToString(); 
    var mockRepo = new Moq.Mock<ISdkRepository>(); 
    var sdks = new HashSet<Sdk>() 
    { 
     new Sdk() 
     { 
      Identifier = cid, 
      AccessibleResources = new HashSet<Resource>() 
      { 
       new Resource() 
       { 
        Id = Guid.NewGuid(), 
        Description = "This is sdk" 
       } 
      } 
     } 
    }; 
    mockRepo.Setup(k => k. 
     AllIncluding(It.IsAny<Expression<Func<Sdk,object>>[]>())) 
         .Returns(sdks.AsQueryable); 
    var sdkCtrl = new SdksController(mockRepo.Object); 
    var returnedJson=sdkCtrl.GetResources(cid); 
    returnedJson.ToString(); 
} 

y es tirar:

System.Reflection.TargetParameterCountException: Parámetro recuento desajuste

¿No sabes por qué?

+0

Puede pegar el Stack Trace? – Raghu

Respuesta

4

Creo que has tocado algunas limitaciones aquí con Moq. No maneja bien los parámetros de expresión porque se pueden pasar expresiones como valores en sí. No hay forma de que Moq sepa qué parte de la expresión se pretende resolver y qué parte de la firma.

Además, no recuerdo cuán bien Moq maneja params xx [], pero es muy posible que tenga una combinación de dos problemas aquí.

¿Eres capaz de crear una clase que expone el conjunto de expresiones como una propiedad? De ser así, podría ser posible cambiar la firma de AllIncluding y decirle a Moq que coincida con cualquier instancia de esa clase.

actualización

En el momento de responder a esta era una limitación, pero ahora es posible. Ver la respuesta por Oleksandr Lytvyn

+0

Mire la respuesta de Oleksandr Lytvyn. – Marcel

28

Aunque hay una respuesta marcada como aceptada, creo que hay una manera de burlarse de su repositorio correctamente.

En lugar de

mockRepo.Setup(k => k.AllIncluding(It.IsAny<Expression<Func<Sdk, object>>[]>())) 
        .Returns(sdks.AsQueryable); 

por favor utilice

mockRepo.Setup(k => k.AllIncluding(It.IsAny<Expression<Func<Sdk, object>>[]>())) 
        .Returns((Expression<Func<Sdk, 
         object>>[] includeProperties) => sdks.AsQueryable()); 
+1

Me salvó el día) Tenía exactamente el mismo problema exactamente en el mismo método, ¡su propuesta funciona! –

+0

¡Gracias! me salvó hurgando sobre – trailmax

+0

¡Impresionante! Trabajó. ¿Hay una explicación de cómo funciona (lo que esto realmente hace)? – Marcel

7

Otra solución para resolver este problema es utilizar: .AsQueryable() en lugar de .AsQueryable.

0

Para otras personas que buscan una respuesta a esto, la solución para mí fue agregar el mismo número de parámetros en Setup como en la expresión en Returns.

Por ejemplo:

No trabajar con diferente argumento count

mock.Setup(x => x.DoSomething(It.IsAny<string>(), It.IsAny<string>())) 
       .Returns((string s) => s.ToLower()); 

Trabajar con misma cantidad de argumentos en la expresión en Returns como en Setup

mock.Setup(x => x.DoSomething(It.IsAny<string>())) 
       .Returns((string s1, string s2) => s1.ToLower()); 
Cuestiones relacionadas