mock /PowerMock当…然后没有被调用



当我执行以下测试时,返回的是原始对象而不是模拟对象,因此执行的是真正的方法getLevelCriteriaForLevel(level)(我在调试器中观察到这一点)。为什么会这样呢?我很确定这个昨天已经工作了,我没有改变任何东西。

I already tried

@PrepareForTest({LevelCriteria.class, LevelGenerator.class})

或者像我以前那样使用MockitoJunitRunner,但这也没有帮助。下面是代码(generateConcreteLevel是一个私有方法。只有当我从模拟传递此数据时,才会抛出预期的异常。否则它不会被抛出。测试失败是因为没有抛出异常,因为测试没有使用模拟对象,而是使用真实对象):

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

和test…

@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的白盒直接执行私有方法,我将在重构后做什么,但问题是,为什么当…

假设你的问题是:

为什么真正的方法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之上。

我没有用@PrepareForTestPowerMockRunner。我有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…为什么会有问题呢?

我知道是怎么回事了。不幸的是,您没有看到这个问题的真正问题,因为我简化了这些类:

今天我真正的LevelGenerator实现了一个参数化的构造函数。这就是为什么昨天还行,现在不行了。显然,当不使用标准构造函数时,Mockito存在模拟注入问题。

结果:when…然后按预期工作

相关内容

  • 没有找到相关文章

最新更新