Moq - 如何对方法中的引用进行单元测试更改

时间:2009-04-17 20:54:24

标签: unit-testing mocking moq

另一天,另一个问题。我的服务层有以下方法

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

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

该方法调用此辅助方法来创建新的匹配对象:

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对象复制匹配对象的一些属性(包括id)。

我的单元测试应该验证服务中生成的viewdata对象是否具有id>为了实现这一点,我必须模拟存储库和add方法的行为。但是每次调用时,service方法都会创建一个新的匹配对象,并且存储库上的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 个答案:

答案 0 :(得分:3)

我认为你的问题就在这一行;

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

您在这里实际做的是设置您在测试中声明的第一个匹配对象的ID,而不是在您的服务中创建的新匹配。

因为您将提供给存储库的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));      
}