2011-01-29 4 views
2

Я стараюсь, чтобы проверить мой контроллерASP.NET MVC Test Unit Controller Сбой

[TestMethod] 
    public void Index() 
    { 
     AdminController controller = new AdminController(); 
     ViewResult result = controller.Index() as ViewResult; 
     Assert.IsNotNull(result); 
    } 

Вот Index() код:

public ActionResult Index() 
     { 
      var repository = new PostsRepository(); 
      var posts = repository.GetAllPosts(); 

      return View(posts); 
     } 

Repository:

public class PostsRepository : IPostsRepository 
    { 
     PostsDataContext _dataContext = new PostsDataContext(); 

     public IQueryable<Post> GetAllPosts() 
     { 
      var posts = from t in _dataContext.Posts select t; 
      return posts; 
     } 

     public Post GetPostById(int id) 
     { 
      var post = from t in _dataContext.Posts 
         where t.id == id 
         select t; 
      return post.First(); 
     } 
    } 

Но мой Index() модульного тестирования с ошибкой:

Test method MvcBlog.Tests.Controllers.AdminControllerTest.Index threw exception: 
System.NullReferenceException: Object reference not set to an instance of an object. 

Трассировка стека:

MvcBlog.Models.PostsDataContext..ctor() in C:\Users\cL1Nk3r\Documents\Visual Studio 2010\Projects\MvcBlog\MvcBlog\Models\Posts.designer.cs: line 38 
MvcBlog.Repository.PostsRepository..ctor() in C:\Users\cL1Nk3r\Documents\Visual Studio 2010\Projects\MvcBlog\MvcBlog\Repository\PostsRepository.cs: line 11 
MvcBlog.Controllers.AdminController.Index() in C:\Users\cL1Nk3r\Documents\Visual Studio 2010\Projects\MvcBlog\MvcBlog\Controllers\AdminController.cs: line 19 
MvcBlog.Tests.Controllers.AdminControllerTest.Index() in C:\Users\cL1Nk3r\Documents\Visual Studio 2010\Projects\MvcBlog\MvcBlog.Tests\Controllers\AdminControllerTest.cs: line 19 

Почему это ошибка?
Если я просто запустил приложение, он работает правильно.

скачать код Источник: http://dl.dropbox.com/u/14053604/MvcBlog.rar

+0

Вы можете поделиться исходным кодом? Я не могу понять, почему вы DataContext выдает исключение. – Restuta

+0

Здесь: http://dl.dropbox.com/u/14053604/MvcBlog.rar – Sergey

ответ

6

Проблема заключается в следующей строке в своем действии контроллера:

var repository = new PostsRepository(); 

Здесь вы зафиксируете ваш контроллер к конкретной реализации хранилища, что делает его очень трудно единицу испытание в изоляции. Для достижения более слабая связи между вашим контроллером и доступом к данным слоя я рекомендовал бы вам с помощью инъекции конструктора:

public class PostsController: Controller 
{ 
    private readonly IPostsRepository _repository; 
    public PostsController(IPostsRepository repository) 
    { 
     _repository = repository; 
    } 

    public ActionResult Index() 
    { 
     var posts = _repository.GetAllPosts(); 
     return View(posts); 
    } 
} 

Теперь контроллер полностью отделен от конкретной реализации хранилища, которое может зависеть от базы данных и т.д. Теперь вы можете использовать насмешливую структуру, такую ​​как Rhino Mocks или Moq, чтобы предоставить фиктивную реализацию этого репозитория для модульного теста.

Лично мне очень нравится MVCContrib TestHelper, который работает с Rhino Mocks и позволяет очень элегантные модульные тесты действий контроллера. Поэтому, как только вы отключили контроллер от конкретной реализации хранилища, как я показал, вы можете провести следующий модульный тест:

[TestMethod] 
public void PostsController_Index_Action_Should_Fetch_All_Posts_From_Repository() 
{ 
    // arrange 
    var postsRepositoryStub = MockRepository.GenerateStub<IPostsRepository>(); 
    var sut = new PostsController(postsRepositoryStub); 
    var expectedPosts = new Post[0]; 
    postsRepositoryStub.Stub(x => x.GetAllPosts).Return(expectedPosts); 

    // act 
    var actual = sut.Index(); 

    // assert 
    actual 
     .AssertViewRendered() 
     .WithViewData<IEnumerable<Post>>() 
     .ShouldBe(expectedPosts); 
} 
+0

Это та же ошибка – Sergey

+0

@Sergey, с моим кодом невозможно получить ту же ошибку просто потому, что код, указанный в сообщении об ошибке расположенный в 'PostsRepository' **, никогда не выполняется ** в модульном тесте. Я использую ложный репозиторий. –

+0

Но почему он работает правильно, когда я выполняю свое приложение? – Sergey