2009-05-19 17 views
6

Mam metody działania jak to w moim kontrolerJak można ustawić ISingleResult? Czy powinienem? czy istnieje lepsza metoda?

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

    return View(); 
} 

i chciałem zacząć testy dla niej (tak, po tym jak został zbudowany, a nie przed ... ale kod został napisany zanim zacząłem używać TDD tak ...)

i zorientowali się, że dodanie właściwości, takie jak ten do sterownika

public delegate NorthwindDatacontext ContextBuilderDelegate(); 

public ContextBuilderDelegate ContextBuilder { get; set; } 

mogę dodać w czymś konstruktora jak to ...

ContextBuilder =() => new NorthwindDatacontext(); 

wtedy mogłem przetestować ActionMethod ustawienie właściwości ContextBuilder z mock z NorthwindDatacontext

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

... Ale nie znalazłem sposób na wykorzystanie tego powodu wszystkie metody NorthwindDatacontext używać ISingleResult jak returnType i nie mogę znajdź sposób, aby utworzyć obiekt z tym interfejsem. Próbowałem to

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

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

ale to nie działa, ponieważ theResult jest null, gdy przekształca się ISingleResult.

Czy istnieje sposób utworzenia obiektu ISingleResult w celu przetestowania w ten sposób lub robię niewłaściwy sposób robienia rzeczy tutaj?

Dzięki z góry

+0

Dzięki, twoje pytanie i pierwsza odpowiedź naprawdę pomogły mi rozwiązać problem. – Odd

Odpowiedz

3

ToList() jest metoda rozszerzenie dla IEnumerable, która jest łatwo drwić, bo ma tylko jedną metodę użytkownika - GetEnumerator().

Wciąż możesz mieć problemy szyderczy NorthwindDataContext klasę, jeśli jej metody nie są wirtualne ...

Tak czy inaczej, to w jaki sposób mogę rozwiązać podobny problem w mojej piaskownicy, nadzieję, że pomoże:

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

Świetna odpowiedź ... to też bym robił. – womp

+1

Przepraszam, czuję się tutaj jak głupiec, ponieważ nie widzę, jak mogę rozwiązać mój problem. Uważam, że jest to dobre podejście, ale nie rozwiązuje tego, czego potrzebuję. Zajrzałem do filmów MVC Storefront Rob Conery i widzę, że wzór repozytorium jest tym, czego potrzebuję, ale nie jest to łatwe do wdrożenia z Kontekstami LinqToSql, jak widzę. –

+0

Świetna odpowiedź, rozwiązałem mój problem. – Odd

5

Stworzyłem klasę, która zaimplementowała ISingleResult i właśnie umieści w niej Listę. Jestem całkiem nowy w tego rodzaju kodowaniu, więc podczas gdy to zadziałało, używaj na własne ryzyko (i jeśli widzisz dziury po komentarzu).

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 
} 

Można to następnie wykorzystać do częściowego przywrócenia. W ten sposób użyłem go z 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

Bardzo dobrze, +1. Używam tej klasy z kilkoma zmianami: 1. '_list' jest' IEnumerable 'zamiast' List '. 2. Przekazuję kolekcję gotową do użycia w konstruktorze klas zamiast metody "Dodaj". – Konamiman

Powiązane problemy