2013-07-01 75 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

我想你是对的。我已经写过你所建议的单元测试。非常感谢你。 –