如何使用最小起订量为受保护方法设置模拟值?

发布于 2024-10-31 17:26:51 字数 1720 浏览 1 评论 0原文

例如,采用以下类:

class GameBoard    
{
    public double Evaluate(PieceType cpusPieceType)
    {
        ...
        for (var i = 0; i < _tableRepository.Size; ++i)
            for (var j = 0; j < _tableRepository.Size; ++j)
                 if (_tableRepository [i, j] != PieceType.Empty)
                 {
                     var isMax = _tableRepository [i, j] == cpusPieceType;

                     var value = EvaluatePosition (i, j, _tableRepository [i, j]);
                     ...
                 }
        ...
    }

    protected virtual double EvaluatePosition (int row, int column, PieceType pieceType)
    { ... }
}

我想为 Evaluate 函数编写一个测试,但这又取决于声明为 protected 的 EvaluatePosition 函数返回的值。现在,我的想法是我可以使用这样的类:

class XGameBoard : GameBoard
{
    protected override double EvaluatePosition (int row, int column, PieceType pieceType)
    {
        // this will call EvaluatePosition_ShouldReturn which will be mocked and have a value previously set up
        return EvaluatePosition_ShouldReturn (row, column, pieceType);
    }
    public virtual double EvaluatePosition_ShouldReturn (int row, int column, PieceType pieceType)
    {
        return base.EvaluatePosition (row, column, pieceType);
    } 
}

测试将如下所示:

_gameBoardMock = new Mock<XGameBoard>(...);

for (var i = 4; i < _size - 4; i += 2)
    for (var j = 4; j < _size - 4; j += 2)
        _gameBoardMock.Setup (x => x.EvaluatePosition_ShouldReturn (i, j, PieceType.Cross)).Returns (1.0);

var result = _gameBoardMock.Object.Evaluate (PieceType.Cross);

问题是 Evaluate 函数内的 EvaluatePosition 始终返回 0,并且不会调用应该返回设置的值的重写函数。

提前致谢。

For example take the following class:

class GameBoard    
{
    public double Evaluate(PieceType cpusPieceType)
    {
        ...
        for (var i = 0; i < _tableRepository.Size; ++i)
            for (var j = 0; j < _tableRepository.Size; ++j)
                 if (_tableRepository [i, j] != PieceType.Empty)
                 {
                     var isMax = _tableRepository [i, j] == cpusPieceType;

                     var value = EvaluatePosition (i, j, _tableRepository [i, j]);
                     ...
                 }
        ...
    }

    protected virtual double EvaluatePosition (int row, int column, PieceType pieceType)
    { ... }
}

I would like to write a test for Evaluate function but this in turn depends on the values returned by EvaluatePosition function which is declared protected. Now, my idea was that I could use a class like:

class XGameBoard : GameBoard
{
    protected override double EvaluatePosition (int row, int column, PieceType pieceType)
    {
        // this will call EvaluatePosition_ShouldReturn which will be mocked and have a value previously set up
        return EvaluatePosition_ShouldReturn (row, column, pieceType);
    }
    public virtual double EvaluatePosition_ShouldReturn (int row, int column, PieceType pieceType)
    {
        return base.EvaluatePosition (row, column, pieceType);
    } 
}

The test would look like this:

_gameBoardMock = new Mock<XGameBoard>(...);

for (var i = 4; i < _size - 4; i += 2)
    for (var j = 4; j < _size - 4; j += 2)
        _gameBoardMock.Setup (x => x.EvaluatePosition_ShouldReturn (i, j, PieceType.Cross)).Returns (1.0);

var result = _gameBoardMock.Object.Evaluate (PieceType.Cross);

The problem is that EvaluatePosition inside the Evaluate function always returns 0, and not the overriden function is invoked which should return the value that was set up.

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小草泠泠 2024-11-07 17:26:51

很难说返回什么值,因为您用 ... 代替了任何返回值。据我所知,您的生产代码循环从 0 开始,一直到电路板的大小,而您的模拟设置则针对特定的组合。

如果您希望设置所有组合,那么就不要在测试中进行循环,只需执行以下

_gameBoardMock.Setup (x => x.EvaluatePosition_ShouldReturn (
      It.IsAny<int>(), 
      It.IsAny<int>(), 
      It.IsAny<PieceType>())).Returns (1.0);

操作即可:但是如果不了解如何从 Evaluate 方法返回值,那么可能会出现以下情况:是其他原因。

另一种选择是根本不使用最小起订量。由于您有一个派生类,您只需更改受保护的方法即可返回您的值。

protected override double EvaluatePosition (int row, int column, PieceType pieceType)
{
    return 1.0;
}

It is hard to say what value is being returned as you have ... in place of any return. From what I can see though your production code loops start from 0 and go through to the size of the board whereas your mock setup targets specific combinations.

If you wanted all combinations to be setup then just doon't to the loop in the test and simply do:

_gameBoardMock.Setup (x => x.EvaluatePosition_ShouldReturn (
      It.IsAny<int>(), 
      It.IsAny<int>(), 
      It.IsAny<PieceType>())).Returns (1.0);

But without seeing what logic you have around how a value is returned from the Evaluate method then there might be some other reason.

Another option is not to use MOQ at all. Since you have a derived class you can simply change the protected method to return your value.

protected override double EvaluatePosition (int row, int column, PieceType pieceType)
{
    return 1.0;
}
梦萦几度 2024-11-07 17:26:51

我想把这个问题再澄清一点。情况是 Evaluate 函数应该根据某些逻辑和 EvaluatePosition 函数的返回值返回一个 double 值。基本上,Evaluate 函数取决于 EvaluatePosition 函数返回的值,但该函数必须单独测试,因此我必须为 EvaluatePosition 函数创建一个存根,并通过最初设置这些值来模拟返回值。我的方法似乎可用,唯一需要的是以下语句:

_gameBoardMock.CallBase = true;

因为 EvaluatePosition 函数被声明为受保护的,所以它应该返回的值不能由 Moq 设置,因此我创建了 XGameBoard 类,该类声明了 EvaluatePosition_ShouldReturn 函数,该函数是公共且可由 Moq 使用,这样我就可以设置正常 EvaluatePosition 函数应返回的值:

_gameBoardMock.Setup (x => x.EvaluatePosition_ShouldReturn (i, j, PieceType.Cross)).Returns (1.0);

因为 EvaluatePosition 函数在 XGameBoard 类中被重写,所以当调用此函数时,它将调用 EvaluatePosition_ShouldReturn 函数,其值由以下设置起订量并应返回指定的值。

我希望有些人可能会发现这种方法对于单元测试很有用。快乐编码。

I would like to clarify the problem a little more. The situation is that the Evaluate function should return a double value based on some logic and the returned values of the EvaluatePosition function. Basically, the Evaluate function depends on the values returned by EvaluatePosition function, but the function has to be tested in isolation so I had to create a stub for the EvaluatePosition function and mimic the return values by setting up those initially. My approach seems to be usable the only thing that is needed is the following statement:

_gameBoardMock.CallBase = true;

Because the EvaluatePosition function is declated protected the values that it should return cannot be set up by Moq, therefore I created the XGameBoard class that declares the EvaluatePosition_ShouldReturn function which is public and usable by Moq and this way I can set up the values that the normal EvaluatePosition function should return:

_gameBoardMock.Setup (x => x.EvaluatePosition_ShouldReturn (i, j, PieceType.Cross)).Returns (1.0);

Because the EvaluatePosition function is overriden in the XGameBoard class, when this function is invoked it will invoke the EvaluatePosition_ShouldReturn function whose values are set up by Moq and should return the specified values.

I hope that some may find this approach useful for unit testing. Happy coding.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文