Domanda

Sto usando ASP.NET MVC 3, MVCContrib, Nunit e Rhino Mocks. Ho pubblicato questo ma non sono riuscito a ottenere una risposta. Le persone si stanno concentrando maggiormente sulla mia codifica che mi aiuta a ottenere una risposta decente per far passare questo test.

Sto cercando di testare la mia vista di modifica. Non sono sicuro di come codificare il test per la vista. È una visione fortemente tipizzata del tipo NewsEditViewData.

Quando la vista si carica, ottiene i dati di un elemento di notizie per ID dal servizio di notizie. Quindi nel mio test ho creato uno stub del servizio di notizie:

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

Ora ho bisogno di mappare questo elemento di notizie su NewsDitViewData. Ho un mapper (Automapper) che lo fa per me, e nel mio test ho fatto quanto segue:

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

Non sono sicuro di essere sulla strada giusta finora?

Quindi ho il seguente pezzo di codice:

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

Non lavorare dal mio codice, voglio una risposta che segue le migliori pratiche. Allora di cosa devo verificare tutti nella mia parte Assert? Devo anche verificare che sia stato restituito un record? Stavo pensando in linea con qualcosa di simile:

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

Questo fallisce. Qualcuno può aiutarmi a riscrivere questo test in modo che supera. Voglio che controlli tutto ciò che deve essere controllato.

Ecco il test completo:

[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);
}

Aggiornamento 2011-02-14:

Nel mio notiziario ho quanto segue:

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
}

Il metodo di azione sembra questo:

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);
}

L'errore che sto ricevendo in nunit è:

Myproject.web.unittests.controllers.newscontrollertests.edit_renderview_editview: mvccontrib.testhelper.assertionException: era myproject.web.common.viewdata.newseditviewdata ma si aspettava myproject.web.web.viewdata

È stato utile?

Soluzione

Non hai mostrato nessuno dei tuoi controller, repository, modelli. È una domanda vicina a impossibile rispondere senza queste informazioni. Quindi iniziamo a indovinare. Hai un modello e un modello di vista:

public class News { }
public class NewsEditViewData { }

Li lascio senza proprietà ai fini di questo post. Quindi probabilmente hai un servizio responsabile del recupero e del salvataggio del modello (il modello di visualizzazione non dovrebbe mai apparire come argomento in/out del tuo livello di servizio). Il servizio non dovrebbe mai conoscere il modello di visualizzazione:

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

Allora probabilmente hai un mapper:

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

E finalmente suppongo che tu abbia un controller che stai cercando di testare:

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);
    }
}

OK, fino a quando qui sei tu che avrebbe dovuto fornire queste informazioni.

E ora posso iniziare a rispondere alla tua domanda sul test unitario che potrebbe apparire così:

[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));
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top