当我执行以下测试时,将返回原始对象而不是模拟,因此正在执行实际方法 getLevelCriteriaForLevel(level)(我在调试器中观察到)。为什么会这样?我很确定昨天这已经奏效了,而且我没有改变任何东西。
我已经尝试了
@PrepareForTest({LevelCriteria.class, LevelGenerator.class})
或者像以前一样使用MockitoJunitRunner,但这也没有帮助。 这是代码(generateConcreteLevel是一个私有方法。只有当我从mock传递这个数据时才抛出预期的异常。否则它不被抛出。测试失败,因为没有抛出异常,因为测试没有&# 39;使用模拟对象,但使用真实对象):
public class LevelGenerator
{
public void createLevel(int level)
{
generateConcreteLevel(levelCriteria.getLevelCriteriaForLevel(level));
}
private void generateConcreteLevel(LevelCriterion levelCriterion)
{
int entryGroupCount = levelCriterion.getEntryGroupCount();
int exitGroupCount = levelCriterion.getExitGroupCount();
int exitsWhileEntries = levelCriterion.getExitsWhileEntries();
int maxGroupSize = levelCriterion.getMaxGroupSize();
List<Question> questions = levelCriterion.getQuestions();
int speed = levelCriterion.getSpeed();
Range blueItemsCount = levelCriterion.getBlueItemsCount();
Range brownItemsCount = levelCriterion.getBrownItemsCount();
Range greenItemsCount = levelCriterion.getGreenItemsCount();
Range redItemsCount = levelCriterion.getRedItemsCount();
Range whiteItemsCount = levelCriterion.getWhiteItemsCount();
Range timespanBetweenGroups = levelCriterion.getTimespanBetweenGroups();
float fractionOfCarAmountToLeave = levelCriterion.getFractionOfCarAmountToLeave();
float fractionOfMinimumItemsAmountInCarParkToStartExits = levelCriterion.getFractionOfMinimumItemsAmountInCarParkToStartExits();
checkItemsFitInEntryGroups(entryGroupCount, maxGroupSize, blueItemsCount, brownItemsCount, greenItemsCount, redItemsCount, whiteItemsCount);
}
private void checkItemsFitInEntryGroups(int entryGroupCount, int maxGroupSize, Range... ranges)
{
int totalRangeCount = 0;
for (Range range : ranges)
{
totalRangeCount += range.getMaximum();
}
if (totalRangeCount > entryGroupCount * maxGroupSize)
{
throw new UnsupportedOperationException("Error in level criterion: Not enough entry groups for Items.");
}
}
}
和测试...
@RunWith(PowerMockRunner.class)
public class LevelGeneratorTest
{
@Mock
private LevelCriteria levelCriteriaMock;
@InjectMocks
private LevelGenerator levelGenerator;
@Test(expected=UnsupportedOperationException.class)
public void tooLessPositionsInEntryGroups()
{
LevelCriterion levelCriterion = new LevelCriterion.LevelCriterionBuilder()
.withBlueItemsCount(new Range(10, 10))
.withEntryGroupCount(3)
.withExitGroupCount(3)
.withMaxGroupSize(3)
.build();
when(levelCriteriaMock.getLevelCriteriaForLevel(anyInt())).thenReturn(levelCriterion);
levelGenerator.createLevel(0);
}
}
顺便说一下:它不是Eclipse问题,因为Maven构建会产生相同的错误。 我知道我可以直接使用PowerMockito的Whitebox执行私有方法,我将在重构后执行该操作,但问题是,为什么......当时在这里不起作用。
答案 0 :(得分:0)
假设您的问题是:
为什么在我希望有模拟实现时执行真正的方法getLevelCriteriaForLevel(level)?
我将尝试演示如果您重现它,一切都按预期正常工作是一个简单的示例(如果需要,从当前工作区切换)。
我没有你LevelCriterion.LevelCriterionBuilder()
所以我通过实例化一个LevelCriterion
(空对象)简化了你的测试。这是不相关的,因为在我的实现中,我将始终返回UnsupportedOperationException。
以下是我的LevelGenerator的样子。 UnsupportedOperationException尽可能简单LevelGenerator#generateConcreteLevel(LevelCriterion)。
如果实施如下:
public class LevelGenerator
{
LevelCriteria levelCriteria;
public void createLevel(int level)
{
generateConcreteLevel(levelCriteria.getLevelCriteriaForLevel(level));
}
private void generateConcreteLevel(LevelCriterion levelCriteriaForLevel)
{
throw new UnsupportedOperationException("xxx");
}
}
测试为绿色,@RunWith(MockitoJUnitRunner.class)
顶部使用LevelGeneratorTest
。
我没有使用@PrepareForTest
或PowerMockRunner
。我有Mockito版本1.9.5。
我确信我没有使用真正的getLevelCriteriaForLevel(level)
实现,因为它看起来像这样:
public class LevelCriteria {
public LevelCriterion getLevelCriteriaForLevel(int level) {
throw new IllegalStateException("Unexpected call");
}
}
如果真正的getLevelCriteriaForLevel(int)被执行,则测试为红色(因为抛出了IllegalStateException)。
测试仍然是绿色的......
这适用于纯Mockito(版本1.9.5)方法。 您应该删除所有其他模拟库(PowerMock,EasyMock ...)
您确定when(..).thenReturn(..)
的静态通话是Mockito吗?
您是否尝试过:Mockito.when(..).thenReturn(..)
我希望它有所帮助。
PS:我看到你更新了这个问题。这对我来说有点不公平,但我不会再次更新我的答案。
我不需要generateConcreteLevel(..)
的实施细节来说明when(..)
调用是否有效。再次阅读我的回答。在单独的工作区中试用它,您将自己看到。
PS-2:我也在使用Eclipse ......为什么会出现问题? Eclipse是一个很棒的IDE。
答案 1 :(得分:0)
我发现了什么是错的。不幸的是,你没有看到这个问题中的真正问题,因为我简化了类:
我的LevelGenerator真正实现了今天的参数化构造函数。这就是为什么它在昨天工作但不再存在的原因。显然,当不使用标准构造函数时,Mockito会出现模拟注入问题。
结果:时间...然后按预期工作。