例如:
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函数写一个测试,但这反过来取决于EvaluatePosition函数返回的值,该函数被声明为protected。现在,我的想法是,我可以使用这样的类:
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,而不是调用被覆盖的函数,它应该返回设置的值。
很难说返回什么值,因为您有...
代替任何返回。从我所看到的,虽然您的生产代码循环从0开始,并通过到板的大小,而您的模拟设置针对特定的组合。
如果你想设置所有的组合,那么就不要在测试中执行循环,只需执行:
_gameBoardMock.Setup (x => x.EvaluatePosition_ShouldReturn (
It.IsAny<int>(),
It.IsAny<int>(),
It.IsAny<PieceType>())).Returns (1.0);
但是如果没有看到关于如何从Evaluate
方法返回值的逻辑,那么可能会有其他原因。
另一个选择是根本不使用最小起订量。因为你有一个派生类,你可以简单地修改protected方法来返回你的值。
protected override double EvaluatePosition (int row, int column, PieceType pieceType)
{
return 1.0;
}
我想再澄清一下这个问题。这种情况是,Evaluate函数应该根据一些逻辑和EvaluatePosition函数的返回值返回一个双精度值。基本上,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函数,它的值是由Moq设置的,应该返回指定的值。
我希望有些人会发现这种方法对单元测试很有用。快乐的编码。