views:

343

answers:

1

Another day , another question. My service layer has the following method

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

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

The method calls the this helper method to create a new match object:

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

The repository stores the given match object and sets the id to some value > 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);
}

The matchviewdata object copies some properties of the the match object (including the id).

My unit test should verify that the resulting viewdata object in the service has an id > 0. To archieve this, i have to mock the repository and the behaviour of the add method. But the service method creates a new match object every time its been called and the add method on the repository updates the referenced match object (there is no need for a return value). I have no idea to solve this with moq.

This is my unit test so far:

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

I tried some other variations - nothing works.

+2  A: 

It looks to me your problem is in this line;

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

What you're actually doing here is setting the id of the first match object you have declared in your test, NOT the new match created in your service.

Because the Match object you will be supplying to the Repository is created internally, I can't think of an easy way to reference it in your Test method to setup a callback for it. To me, this is a sign you may be trying to test too much in one unit test.

I think you should simply test that the Add method is called and write a separate test to ensure that it works as exepected.

I propose something like this;

[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));      
}
Kirschstein
Oh dear. Of cource you are right :-) (and I already had the second test). But sometimes you don't see the wood for the trees... Thanks
Herr W.