Moq - Как выполнить юнит-тест изменений на ссылку в методе - PullRequest
2 голосов
/ 18 апреля 2009

Еще один день, другой вопрос. Мой сервисный слой имеет следующий метод

public MatchViewData CreateMatch(string user)
{
    var matchViewData = !HasReachedMaxNumberOfMatchesLimit(user) ?
        CreateMatchAndAddToRepository(user) : 
        MatchViewData.NewInstance(new Match(user));

    matchViewData.LimitReached = HasReachedMaxNumberOfMatchesLimit(user);
    return matchViewData;
}

Метод вызывает вспомогательный метод this для создания нового объекта сопоставления:

private MatchViewData CreateMatchAndAddToRepository(string user)
{
    var match = new Match(user);
    MatchRepository.Add(match);
    return MatchViewData.NewInstance(match);
}

В хранилище хранится заданный объект сопоставления и устанавливается значение id, равное> 0.

public void Add(Match match)
{
    Check.Require(match != null);
    var numberOfMatchesBefore = Matches.Count;
    SetIdPerReflection(match, NextVal());
    Matches.Add(match);
    Check.Ensure(numberOfMatchesBefore == Matches.Count - 1);
}

Объект matchviewdata копирует некоторые свойства объекта соответствия (включая идентификатор).

Мой модульный тест должен проверить, что результирующий объект viewdata в сервисе имеет id> 0. Чтобы архивировать это, я должен смоделировать хранилище и поведение метода add. Но сервисный метод создает новый объект сопоставления каждый раз, когда он вызывается, и метод add в хранилище обновляет ссылочный объект сопоставления (возвращаемое значение не требуется). Я понятия не имею, чтобы решить это с moq.

Пока это мой модульный тест:

[Test]
public void ServiceCreateMatchReturnedMatchViewDataHasNonZeroId()
{
    var match = TestUtils.FakePersistentMatch(User, 1);
    var repositoryMock = new Mock<IMatchRepository>();
    repositoryMock.Setup(
           r => r.Add(It.IsAny<Match>())).Callback(() => match.Id = 1);
    var serviceFacade = new DefaultServiceFacade(repositoryMock.Object);

    var returnedMatch = serviceFacade.CreateMatch(User);

    Assert.That(returnedMatch.Id, Is.GreaterThan(0));
}

Я пробовал другие варианты - ничего не работает.

1 Ответ

3 голосов
/ 18 апреля 2009

Мне кажется, ваша проблема в этой строке;

repositoryMock.Setup(
       r => r.Add(It.IsAny<Match>())).Callback(() => match.Id = 1);

То, что вы на самом деле здесь делаете, это установка идентификатора первого объекта сопоставления, который вы объявили в своем тесте, а НЕ нового совпадения, созданного в вашем сервисе.

Поскольку объект Match, который вы будете предоставлять в репозиторий, создается внутри, я не могу придумать простой способ ссылки на него в вашем методе Test для настройки обратного вызова для него. Для меня это признак того, что вы можете слишком много тестировать в одном модульном тесте.

Я думаю, вам следует просто проверить, что метод Add вызывается, и написать отдельный тест, чтобы убедиться, что он работает должным образом.

Я предлагаю что-то вроде этого;

[Test]
public void ServiceAddsNewMatchToRepository()
{
   var repositoryMock = new Mock<IMatchRepository>();
   bool addCalled = false;
   repositoryMock
       .Expect(r => r.Add(It.Is<Match>(x => x.Id == 0))
       .Callback(() => addCalled = true);

   var serviceFacade = new DefaultServiceFacade(repositoryMock.Object);
   serviceFacade.CreateMatch(User);

   Assert.True(addCalled);
}

....

[Test]
public void AddingANewMatchGeneratesANewId()
{
  var match = new Match(user);
  var matchRepository = new MatchRepository();
  var returnedMatch = matchRepository.Add(match);

  Assert.That(returnedMatch.Id, Is.GreaterThan(0));      
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...