Сбой проверки модуля контроллера ASP.NET MVC - PullRequest
2 голосов
/ 30 января 2011

Я пытаюсь проверить мой контроллер

[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

1 Ответ

6 голосов
/ 30 января 2011

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

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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...