Тестирование представления редактирования с помощью MVCContrib Test Helper - PullRequest
0 голосов
/ 11 февраля 2011

Я использую ASP.NET MVC 3, MVCContrib, NUnit и Rhino Mocks.Я отправил это, но не мог получить ответ.Люди больше внимания уделяют моему кодированию, которое помогает мне получить достойный ответ для прохождения этого теста.

Я пытаюсь проверить мой вид редактирования.Я не уверен, как закодировать тест для представления.Это строго типизированное представление типа NewsEditViewData.

Когда загружается представление, оно получает данные элемента новостей по идентификатору из службы новостей.Итак, в своем тесте я создал заглушку службы новостей:

var id = 1;
var news = new News();
newsServiceStub
   .Stub(x => x.FindById(id))
   .Return(news);

Теперь мне нужно сопоставить этот элемент новостей с NewsEditViewData.У меня есть картограф (AutoMapper), который делает это для меня, и в своем тесте я сделал следующее:

newsMapperStub
   .Stub(x => x.Map(news, typeof(News), typeof(NewsEditViewData)))
   .Return(newsEditViewData);

Я не уверен, что пока на правильном пути?

Тогда у меня есть следующий фрагмент кода:

// Act
var actual = sut.Edit(id);

Не работайте из своего кода, я хочу получить ответ, следуя рекомендациям.Так что все, что мне нужно проверить в моей части утверждения?Нужно ли также проверять, что запись была возвращена?Я думал о чем-то вроде:

actual
   .AssertViewRendered()
   .WithViewData<NewsEditViewData>()
   .ShouldBe(newsEditViewData);

Это не удалось.Может кто-нибудь, пожалуйста, помогите мне переписать этот тест, чтобы он прошел.Я хочу, чтобы он проверил все, что нужно проверить.

Вот полный тест:

[Test]
public void Edit_should_render_Edit_view()
{
   // Arrange
   var id = 1;
   var news = new News();
   var newsEditViewData = new NewsEditViewData();

   newsServiceStub
      .Stub(x => x.FindById(id))
      .Return(news);

   newsMapperStub
      .Stub(x => x.Map(news, typeof(News), typeof(NewsEditViewData)))
      .Return(newsEditViewData);

   // Act
   var actual = sut.Edit(id);

   // Assert
   actual
      .AssertViewRendered()
      .WithViewData<NewsEditViewData>()
      .ShouldBe(newsEditViewData);
}

ОБНОВЛЕНИЕ 2011-02-14:

В моем NewsController у меня есть следующее:

private INewsService newsService;
private IMapper newsMapper;

public NewsController(INewsService newsService)
{
   Check.Argument.IsNotNull(newsService, "newsService");

   this.newsService = newsService;
   newsMapper = new NewsMapper();  // TODO: Use dependency injection
}

Метод действия выглядит так:

public ActionResult Edit(int id)
{
   Check.Argument.IsNotZeroOrNegative(id, "id");

   var news = newsService.FindById(id);
   var newsEditViewData = (NewsEditViewData)newsMapper.Map(news, typeof(News), typeof(NewsEditViewData));

   return View(newsEditViewData);
}

Ошибка, которую я получаю в NUnit:

MyProject.Web.UnitTests.Controllers.NewsControllerTests.Edit_RenderView_EditView: MvcContrib.TestHelper.AssertionException: был MyProject.Web.Common.ViewData.NewsEditViewData, но ожидаемый 10ata.Dite

1 Ответ

2 голосов
/ 11 февраля 2011

Вы не показали ни одного из ваших контроллеров, репозитория, моделей. На этот вопрос почти невозможно ответить без этой информации. Итак, давайте начнем гадать. У вас есть модель и вид модели:

public class News { }
public class NewsEditViewData { }

Я оставляю их без каких-либо свойств для целей этого поста. Тогда у вас, вероятно, есть служба, которая отвечает за извлечение и сохранение вашей модели (модель представления никогда не должна появляться в качестве аргумента in / out вашего уровня обслуживания). Сервис никогда не должен знать о представлении модели:

public interface INewsService
{
    News FindById(int id);
    void CreateNews(News news);
}

Тогда у вас, вероятно, есть картограф:

public interface IMapper
{
    object Map(object source, Type sourceType, Type destinationType);
}

И, наконец, я предполагаю, что у вас есть контроллер, который вы пытаетесь проверить:

public class NewsController : Controller
{
    private readonly INewsService _newsService;
    private readonly IMapper _newsMapper;

    public NewsController(INewsService newsService, IMapper newsMapper)
    {
        _newsService = newsService;
        _newsMapper = newsMapper;
    }

    public ActionResult Edit(int id)
    {
        // WARNING: Meaningless action ahead as it retrieves some
        // model from the service and passes this model to
        // the service back again for update. In the meantime
        // the model is converted to a view model using a mapper
        // and passed to the view. So totally meaningless in a real 
        // application but let's consider for the purpose of this demonstration
        var news = _newsService.FindById(id);
        _newsService.CreateNews(news);
        var newsEditViewData = (NewsEditViewData)_newsMapper.Map(news, typeof(News), typeof(NewsEditViewData));
        return View(newsEditViewData);
    }
}

Хорошо, до этого момента именно вы должны были предоставить эту информацию.

И теперь я могу начать отвечать на ваш вопрос о модульном тесте, который может выглядеть следующим образом:

[Test]
public void Edit_should_fetch_news_model_from_service_given_an_id_parameter_create_news_and_pass_a_viewmodel_to_the_view()
{
    // arrange
    // TODO : move this part in the initialization section 
    // of your unit test to avoid repeating it on each method
    var newsServiceStub = MockRepository.GenerateStub<INewsService>();
    var newsMapperStub = MockRepository.GenerateStub<IMapper>();
    var sut = new NewsController(newsServiceStub, newsMapperStub);
    new TestControllerBuilder().InitializeController(sut);

    var news = new News();
    var id = 123;
    var newsEditViewData = new NewsEditViewData();
    newsServiceStub
        .Stub(x => x.FindById(id))
        .Return(news);

    newsMapperStub
        .Stub(x => x.Map(news, typeof(News), typeof(NewsEditViewData)))
        .Return(newsEditViewData);

    // act
    var actual = sut.Edit(id);

    // assert
    actual
        .AssertViewRendered()
        .WithViewData<NewsEditViewData>()
        .ShouldBe(newsEditViewData);
    newsServiceStub.AssertWasCalled(x => x.CreateNews(news));
}
...