2013-07-01 76 views
3

我得到非常困惑時,我有單元測試值爲調用其他類的多個公共方法的方法的方法。這裏是例子單元測試是依賴於其他公共方法

using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 
using SkillKindle.BLL; 
using SkillKindle.BLL.ClassDetails; 
using SkillKindle.BLL.SkClasses; 
using SkillKindle.Domain.Models.SkClasses; 
using SkillKindle.Infrastructure; 
using SkillKindle.Web.Core.Infrastructure.ErrorHandling; 
using SkillKindleWeb.Mappers; 
using SkillKindleWeb.ViewModels.ClassDetails; 

namespace SkillKindleWeb.Controllers 
{ 
    [CustomHandleError(ExceptionType = typeof (BusinessValidationException))] 
    public class ClassDetailsController : BaseController 
    { 
     private readonly ILogger _logger; 
     private readonly IMapperService _mapperService; 
     private readonly IAccessorFactory _accessorFactory; 
     private const int RegistrationId = 34; 

     private IClassDetailsAccessor ClassDetailsAccessor 
     { 
      get { return _accessorFactory.CreateClassDetailsAccessor(); } 
     } 

     private ISkClassAccessor SkClassAccessor 
     { 
      get { return _accessorFactory.CreateSkClassAccessor(); } 
     } 

     private IClassCreativeAccessor ClassCreativeAccessor 
     { 
      get { return _accessorFactory.CreateClassCreativeAccessor(); } 
     } 

     public ClassDetailsController(ILogger logger, IMapperService mapperService, 
             IAccessorFactory accessorFactory) 
     { 
      _logger = logger; 
      _mapperService = mapperService; 
      _accessorFactory = accessorFactory; 
     } 

     public ViewResult Index(int classCreativeId) 
     { 
      var classCreative = ClassCreativeAccessor.GetClassCreative(classCreativeId); 
      if (classCreative == null) 
      { 
       throw new HttpException(404, "The url is not valid"); 
      } 

      var batches = ClassCreativeAccessor.GetFutureBatches(classCreativeId); 
      IList<ClassTicket> tickets = new List<ClassTicket>(); 
      IList<Venue> venues = new List<Venue>(); 

      if (batches.Count > 0) 
      { 
       tickets = 
        ClassCreativeAccessor.GetTickets(
         batches.Select(batch => batch.ClassScheduleId).Distinct().ToArray()); 
       venues = SkClassAccessor.GetVenues(batches.Select(batch => batch.VenueId).Distinct().ToArray()); 
      } 

      var classDetailsViewModel = _mapperService.ClassCreativeToClassDetailsViewModel(classCreative); 
      var batchViewModels = _mapperService.BatchToClassDetailsBatchViewModel(batches).ToList(); 
      var ticketViewModels = _mapperService.ClassTicketToClassDetailsTicketViewModel(tickets).ToList(); 
      var venueViewModels = _mapperService.VenueToClassDetailsVenueViewModel(venues).ToList(); 

      var indexViewModel = new IndexViewModel() 
       { 
        Batches = batchViewModels, 
        Tickets = ticketViewModels, 
        ClassDetails = classDetailsViewModel, 
        Venues = venueViewModels 
       }; 
      return View(indexViewModel); 
     } 
    } 
} 

這裏指數的方法是依賴於mapperService,SkClassAccessor,ClassDetailsAccessor, ClassCreativeAccessor公共方法。我已經單元測試了這些公共方法。現在說到測試Index方法,我需要檢查indexViewModel的正確性。這裏有幾個選項與我。

選項1.模擬相關的類返回假的對象和檢查IndexViewModel有那些假對象的公共方法。我不確定這是否是一個真正的考驗。另外它不會測試我是否將這些寫入參數傳遞給這些模擬公共方法。

選項2.不要嘲笑依賴類,但相關類的假依賴的公共方法。例如僞造ClassCreativeAccessor.GetTickets的票單列表。這種方法將驗證我將正確的參數傳遞給相關的公共方法。但在這裏我會測試公衆方法再次

我不知道哪一種方法是正確的。感謝你的幫助。

+0

我認爲你必須與第一種方法去,因爲它是沒有意義的,因爲如果再次測試所有的方法,如果你會改變的功能函數,你必須修復多個單元測試,這不是最佳實踐 – rajansoft1

回答

1

我不知道這是否是一個真正的考驗。

這是因爲它應該是一個單元測試。不要把它和集成測試混在一起。

此外,它不測試我將寫入參數傳遞給這些 模擬公共方法。

當你嘲笑的依賴關係(第一個選項),你總是可以驗證方法被調用適當的參數。例如。與起訂量:

mock.Verify(foo => foo.Execute("ping")); 

會檢查是否依賴foo的方法Execute與參數"ping"調用。您可以驗證您ClassCreativeAccessor同樣的方式被稱爲適當的參數:

int classCreativeId = 42; 
List<Batch> batches = new List<Batch>(); 

creativeAccessorMock.Setup(ca => ca.GetFutureBatches(classCreativeId)) 
        .Returns(batches); 
... 
+1

我想你是對的。我已經寫過你所建議的單元測試。非常感謝你。 –