سؤال

I want to step into the real method using the test data as input.

When GetSurveyList is called it doesn't pay attention to the date I'm giving it. It always returns all three items I manually added to the mockModel. It should be checking the date and only returning those items that have a date that is equal to or greater than the input date.

If I step in I only get as far as the interface also. The next step in call should go to the code that implements the interface and yet it does not. Is this the standard behavior of Moq? I thought it would let you step in?

Here is my code:

[TestMethod]
public void TestHasListOfSurveys()
{
    var mockRepository = new Mock<ISurveyListRepository>();
    var mockModel = new List<SurveyList>();
    mockModel.Add(new SurveyList { SurveyID = 1, SurveyName = "test1", DeliveryDate = DateTime.Parse("1/1/2014") });
    mockModel.Add(new SurveyList { SurveyID = 2, SurveyName = "test2", DeliveryDate = DateTime.Parse("6/1/2014") });
    mockModel.Add(new SurveyList { SurveyID = 3, SurveyName = "test3", DeliveryDate = DateTime.Parse("12/1/2014") });

    string testDate = DateTime.Today.ToShortDateString();

    mockRepository.Setup(x => x.GetSurveyList(testDate)).Returns(mockModel);

    var testClass = new SurveyListModel(mockRepository.Object);
    var testModel = testClass.GetSurveyList(testDate);

    mockRepository.VerifyAll();

    Assert.IsTrue(testModel.Count > 0);
}

GetSurveyList from Repository:

public class SurveyListRepository : ISurveyListRepository

public List<SurveyList> GetSurveyList(String deliveryDateAfterInput)
{
    List<SurveyList> SurveyLists = new List<SurveyList>();
    string error = string.Empty;

    using (OrderingEntities db = DierbergsAppLib.Entities.EntityFactory.GetInstance<OrderingEntities>(
               new DierbergsAppLib.Entities.EntityFactory.EntityFactoryOptions()
               {
                   EntityNameInConfigFile = "OrderingEntities",
                   ConnectionStringCacheManager = new DierbergsAppLib.Entities.WebCacheConnectionStringManager()
               },
               out error))
    {
        DateTime deliveryDateFilter = Convert.ToDateTime(deliveryDateAfterInput);

        var SurveyList = db.uspOrderSurveyListAllStoresGet(deliveryDateFilter);

        foreach (uspOrderSurveyListAllStoresGet_Result viewsurvey in SurveyList)
        {
           // SurveyLists.Add( )
        }
    }

    List<SurveyList> all = SurveyLists.OrderBy(x => x.SurveyDueDate).ToList();
    return all;
}

GetSurveyList from model:

public class SurveyListModel

public List<SurveyList> GetSurveyList(String deliveryDateAfterInput)
{
    return _repository.GetSurveyList(deliveryDateAfterInput);
}
هل كانت مفيدة؟

المحلول

Tests are specifications of your code. Lets think what scenario of SurveyListModel behavior you are trying to specify by this test. In this case logic is very straight-forward:

SurveyListModel should return surveys from repository for specified date

So, if you'll stop and think, then you should not verify dates of returned surveys. SurveyListModel responsibilities does not involve modifying repository response in any way. It should do following - pass date parameter to one specific method of repository, and just return repository response to caller. Nothing else. That's what you should verify.

var repositoryMock = new Mock<ISurveyListRepository>();
string date = DateTime.Today.ToShortDateString();
repositoryMock.Setup(r => r.GetSurveyList(date)).Returns(CreateTestSurveys());
var model = new SurveyListModel(repositoryMock.Object);

var surveys = model.GetSurveyList(date);

repositoryMock.VerifyAll();
CollectionAssert.AreEqual(CreateTestSurveys(), surveys);

This test verifies that

  • survey list called correct method of repository (if method was not called, verification will fail)
  • correct date was passed (if SurveyListModel will pass different date to repository, setup will not be executed)
  • survey list returned exactly same surveys which it got from repository (if SurveListModel will return different surveys, or modify repository response in any way, then assertion should fail).

You should understand, that it really does not matter what repository returns in this scenario. It could be surveys with any dates, or empty list as above. You should just verify that exactly same collection was returned by SUT.

NOTE: Use DateTime to pass date values.

نصائح أخرى

mockRepository.Setup(x => x.GetSurveyList(testDate)).Returns(mockModel);

This sets up your mock repository to return the full model when you GetSurveyList(testDate), meaning that the date is ignored. Presumably SurveyListModel expects to only be getting back the SurveyLists for the date passed in to that method.

If you want it to do the correct thing, then only include a mockModel.Add line with the data you want the mock repository to actually return in your test.

However, now that you've posted the code you're testing, it's clear that this test is pointless. You're mocking out the code that actually does all the work! All the method you're "testing" does is return the mocked data.

Also don't use DateTime.Today as your test date or the test might not work tomorrow!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top