Moq-如何在方法中对参考上的更改进行单元测试 [英] Moq - How to unit test changes on a reference in a method

查看:78
本文介绍了Moq-如何在方法中对参考上的更改进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

存储库存储给定的匹配对象,并将id设置为大于0的某个值.

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

matchviewdata对象复制match对象的某些属性(包括id).

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

我的单元测试应该验证服务中生成的viewdata对象的id>0.要对此进行归档,我必须模拟存储库和add方法的行为.但是,每次调用service方法时都会创建一个新的匹配对象,并且存储库上的add方法会更新引用的匹配对象(无需返回值).我不知道要解决起订量.

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.

推荐答案

在我看来,您的问题在这一行中;

It looks to me your problem is in this line;

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

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

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.

因为要提供给存储库的Match对象是在内部创建的,所以我想不出一种简单的方法在Test方法中引用该对象以为其设置回调.对我来说,这是一个信号,您可能想在一个单元测试中进行过多的测试.

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.

我认为您应该简单地测试Add方法是否被调用,并编写一个单独的测试以确保它按预期工作.

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

我提议像这样的东西

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

这篇关于Moq-如何在方法中对参考上的更改进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆