2009-05-19 9 views
6

tengo un método de acción como esta en mi regulador¿Cómo moq a ISingleResult? ¿Debería? o hay un mejor método?

public ActionResult Index() 
{ 
    using (NorthwindDataContext db = new NorthwindDatacontext()) 
    { 
     var results = db.GetRecordSets(arg1, ....).ToList(); 
     // use results as list 
    } 

    return View(); 
} 

y quería empezar a hacer pruebas para ello (si, después de su construcción, no antes ... pero el código fue escrito antes de empezar a utilizar TDD así que ...)

y me di cuenta de que la adición de una propiedad como ésta al controlador

public delegate NorthwindDatacontext ContextBuilderDelegate(); 

public ContextBuilderDelegate ContextBuilder { get; set; } 

podría añadir en el constructor algo como esto ...

ContextBuilder =() => new NorthwindDatacontext(); 

entonces podría probar la ActionMethod establecer la propiedad ContextBuilder con un simulacro de NorthwindDataContext

var controller    = new MyController(); 
var mockDataContext   = new Mock<NorthwindDatacontext>(); 
controller.ContextBuilder =() => mockDataContext.Object; 

... Pero no he encontrado ninguna manera de utilizar esto porque todos los métodos de NorthwindDataContext utilizan ISingleResult como returnType y no puedo encuentra la manera de crear un objeto con esa interfaz. He intentado esto

var theResult     = new List<GetRecordSetsResult>(); 
// fill the data structure here with the provided result... 

mockDataContext.Setup(c => c. GetRecordSets()).Returns(theResult as 
              ISingleResult<GetRecordSetsResult>); 

pero no funciona porque ycompararlos es nulo cuando se convierte a ISingleResult.

¿Hay alguna manera de crear un objeto ISingleResult para probar de esta manera o estoy haciendo la manera incorrecta de hacer las cosas aquí?

Gracias de antemano

+0

Gracias, su pregunta y la primera respuesta realmente me ayudaron a resolver el problema. – Odd

Respuesta

3

ToList() es un método de extensión de IEnumerable, que es fácil burlarse, ya que sólo tiene un método miembro - GetEnumerator().

Aún es posible que tenga problemas burlones clase NorthwindDataContext, si sus métodos no son virtuales ...

De todas formas, así es como he resuelto un problema similar en mi caja de arena, espero que ayude:

public class MyType 
{ 
    public virtual ISingleResult<int> ReturnSomeResult() { throw new NotImplementedException(); } 
} 

[TestMethod] 
public void TestMethod1() 
{ 
    var mockMyType = new Mock<MyType>(); 
    var mockSingleResult = new Mock<ISingleResult<int>>(); 
    IEnumerable<int> someEnumerable = new int[] {1,2,3,4,5}; 
    mockSingleResult.Setup(result => result.GetEnumerator()).Returns(someEnumerable.GetEnumerator()); 
    mockMyType.Setup(myType => myType.ReturnSomeResult()).Returns(mockSingleResult.Object); 

    Assert.AreEqual(15, mockMyType.Object.ReturnSomeResult().ToList().Sum()); 
} 
+0

Gran respuesta ... esto es lo que yo también haría. – womp

+1

Lo siento, me siento como un tonto aquí porque no puedo ver cómo puedo resolver mi problema. Veo que es un buen enfoque, pero no resuelve lo que necesito. Estaba echando un vistazo a los videos MVC Storefront de Rob Conery y puedo ver que el patrón de repositorio es lo que necesito pero que no se implementa fácilmente con Contextos de datos de LinqToSql, como puedo ver. –

+0

Gran respuesta, resolvió mi problema. – Odd

5

Creé una clase que implementó ISingleResult y simplemente puse una lista en ella. Soy bastante nuevo en este tipo de codificación, así que aunque esto funcionó para mí, utilícelo bajo su propio riesgo (y si ve agujeros, publique un comentario).

class SingleResult<T>:ISingleResult<T> 
{ 
    readonly List<T> _list = new List<T>(); 

    public void Add(T item) 
    { 
     _list.Add(item); 
    } 

    #region Interface Items 

    public IEnumerator<T> GetEnumerator() 
    { 
     return _list.GetEnumerator(); 
    } 

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

    public object ReturnValue { get { return _list; } } 

    public void Dispose() { } 

    #endregion 
} 

Esto se puede utilizar para volver en parte de un simulacro. Así es como terminé usándolo con Rhino Mocks:

[TestMethod] 
public void TestSomething() 
{ 
    //Arrange 
    // Make a data context and DAL 
    var _ctx = MockRepository.GenerateMock<IDataClassesDataContext>(); 
    var someDALClass = new SomeDALClass(_ctx); 

    User testUser = UserObjectHelper.TestUser(); 
    SingleResult<User> userList = new SingleResult<User> { testUser }; 

    // Indicate that we expect a call the to sproc GetUserByUserID 
    _ctx.Expect(x => x.GetUserByUserID(testUser.UserID)).Return(userList); 

    //Act 
    someDALClass.UpdateUser(testUser); 

    //Assert 
    Assert.IsTrue(SomeTestCondition()); 
} 
+0

Muy bien, +1. Estoy usando esta clase con un par de cambios: 1. '_list' es un' IEnumerable 'en vez de' List '. 2. Paso una colección lista para usar en el constructor de la clase en lugar de tener un método 'Add'. – Konamiman

Cuestiones relacionadas