2011-01-20 64 views
2

我完全被这个弄糊涂了。我正在运行一整套完整的单元测试。以下是有关共享代码被使用一些JUnit测试:什么会导致HashMap containsKey()失败并以String为关键字?

private static Map<String, JAXBContext> jaxbContexts = 
          new HashMap<String, JAXBContext>(); 

private synchronized JAXBContext getJAXBContext(Class clazz) throws JAXBException { 
    JAXBContext context = null; 
    if (jaxbContexts.containsKey(clazz.getName())) { 
     context = jaxbContexts.get(clazz.getName()); 
    } else { 
     context = JAXBContext.newInstance(clazz); 
     System.out.println("Created new context for '" + clazz.getName() + "'"); 
     jaxbContexts.put(clazz.getName(), context); 
    } 
    return context; 
} 

从JUnit的运行输出控制台包括以下两个连续的条目:

Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface' 
Created new context for 'com.somecompany.xmlschema.providepensionpaymentinfo.Interface' 

我缺少什么?为什么jaxbContexts.containsKey()在这种情况下不能用于基于字符串的键,与JUnit执行期间的其他46次不同?我们并不是在同时运行我们的测试,但是如果这有所作为,我们会使用Aspects。

+0

您确定这两行之间没有停止/启动JVM吗? – Pointy 2011-01-20 14:20:59

回答

3

调试和验证包含此getJAXBContext()方法的类实例化只有一次(通过检查它在调试模式相同的内存ID为每次调用它)。如果它是不同的实例,那么synchronized关键字将锁定在不同的锁上,它们将使用不同的地图。

+0

谢谢。调试确实验证了(至少)有两个静态jaxbContexts实例。此代码位于具有多个具体实现的抽象基类中。每个子类都有一个这个字段的静态实例吗? – 2011-01-20 14:58:58

1

就我个人而言,我不打扰containsKey。

String name = clazz.getName(); 
context = jaxbContexts.get(name); 
if (context == null) { 
    context = JAXBContext.newInstance(clazz); 
    System.out.println("Created new context for '" + name + "'"); 
    jaxbContexts.put(name, context); 
} 
+0

好的,但这并不影响这个结果,它暗示containsKey正在工作,而我的问题其实在于jaxbContexts的多个静态实例。 – 2011-01-20 14:57:18

+0

是的,我知道这实际上并没有解决问题。这就是为什么我投了@杰弗里的答案。 – 2011-01-20 15:05:28

0

除了比赛......但是你说你不并行运行的东西...

无论如何,我会叫context = jaxbContexts.get(clazz.getName())和测试contextnull

啊,而且使用的类本身作为重点,因为不止一个类可以有相同的名称(认为的类加载器)

1

有一定没有什么特别的包含字符串作为键地图。只需将替换为println,您就会看到发生了什么。你可能正在创建持有地图的类的两个实例,或者其他任何东西。

-1

该地图可以是Map<Class, JAXBContext>而不是Map<String, JAXBContext>以方便使用。

相关问题