java - JMockit 无法模拟来自 JRE 的具体集合

标签 java unit-testing jmockit

我有需要模拟 HashMap 类的测试用例,但 JMockit 在模拟它时似乎遇到了困难。 以下代码在 Expectations block 中触发 NPE:

public class TestKO {

public class ClassUnderTest {

    private final Map<String, String> dependency;

    public ClassUnderTest() {
        this.dependency = new HashMap<String, String>();
    }

    public void register(final String key, final String value) {
        dependency.put(key, value);
    }
}

@Test
public void ko(@Mocked("put") final HashMap<String, String> dep) {
    new Expectations() {{
            dep.put("key", "value"); // dep is null => NullPointerException !
        }};
    final ClassUnderTest c = new ClassUnderTest();
    c.register("key", "value");
}

如果我用任何 POJO 替换 HashMap,JMockIt 可以模拟它并且测试会成功。 事实上,JMockit 似乎无法从 Java 集合框架中模拟任何具体类(也无法模拟任何具体类的派生类)。

下面的测试用例说明了这个问题:

public class MyTests {

public static class POJO {
}

public static class MyMapExtendingConcreteCollection extends HashMap<String, String> {
}

public static class MyMapExtendingAbstractCollection extends AbstractMap<String, String> {

    @Override
    public Set<java.util.Map.Entry<String, String>> entrySet() {
        return null;
    }

}

@Test
public void strangeBehaviors(@Mocked POJO mockedPOJO, @Mocked HashMap<String, String> mockedMap,
        @Mocked ConcurrentHashMap<String, String> mockedConcurrentMap,
        @Mocked MyMapExtendingConcreteCollection mockedMyMapFromConcrete,
        @Mocked MyMapExtendingAbstractCollection mockedMyMapFromAbstract) {
    assertNotNull(mockedPOJO); // OK : not null
    assertNotNull(mockedMap); // FAIL: null !
    assertNotNull(mockedConcurrentMap); // OK : not null
    assertNotNull(mockedMyMapFromConcrete); // FAIL: null !
    assertNotNull(mockedMyMapFromAbstract); // OK: not null
}

我会在使用 JMockit 时产生误解吗?

感谢您的帮助。

最佳答案

由于 JMockit 中的错误,mock 参数为 null,如果它们碰巧被模拟,则会影响某些广泛使用的 JRE 类(包括 ArrayList、HashMap 和其他一些)。

这个 bug 可以修复,但这里真正的问题是是否应该首先允许模拟这些类。在我看来,他们不应该这样做,因为几乎可以肯定没有合法的用例。

在问题中暴露的情况下,测试应该: a) 通过公共(public) getter 或其他方法的返回值验证某些内部集合/映射的状态; b) 或者,作为最后的手段,使用反射来获取对内部状态的访问(mockit.Deencapsulation 在这里可以提供帮助)。

同样的规则应该适用于 AbstractCollectionHashMap 等的子类,因为它们也只是数据持有者,不应该 mock 。更一般地说,java.util.* 接口(interface)方法不应该是可模拟的(有少数异常(exception))。在未来的版本中,JMockit 将在尝试使用 Expectations API 模拟此类方法时抛出描述性异常。

归根结底,无论是因为该工具无法正确模拟它,还是它不会选择模拟它,如果不能编写此类测试,对用户来说是最好的。 “值对象”类和集合/映射根本不应该被 mock ;总是有更好的方法来编写测试。

关于java - JMockit 无法模拟来自 JRE 的具体集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28154108/

相关文章:

java - 简单XML : Value and Attribute on same Node

javascript - 查询字符串总是在服务器端返回 NULL

java - Apache Flink Process Stream 多次

使用 django-nose 的 Django 负载测试装置

.NET 相当于 httpunit

java - jMockit对私有(private)类的访问

java - JMockit 双数组参数的期望

java - JMockit:使用 @Mocked 时期望似乎正在寻找确切的实例

java - 允许 ID = 0 与 Hibernate ("eclipselink.id-validation"= "NULL"等效)

unit-testing - 单元测试 AngularJS 服务