如何创建一个内存中的JarFile



我想写一个函数:

public Map<String, Document> getTestXml(JarFile jarFile) {
    Map<String, Document> result = Maps.newHashMap();
    Enumeration<JarEntry> jarEntries = jarFile.getEntries();
    while (jarEntries.hasMoreElements()) {
        JarEntry jarEntry = jarEntries.nextElement();
        String name = jarEntry.getName();
        if (name.endsWith(".class") && !name.contains("$")) {
            String testClassName = name.replace(".class", "").replace("/", ".");
            String testXmlFilename = "TEST-" + testClassName + ".xml";
            InputStream testXmlInputStream = testJarFile.getInputStream(
                    testJarFile.getJarEntry(testXmlFilename));
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            Document testXmlDocument = documentBuilder.parse(testXmlInputStream);
            result.put(testClassName, testXmlDocument);
        }
    }
    return result;
}

我想写一个单元测试,它实际上不会在文件系统上创建一个JarFile。我试图寻找如何在内存中创建一个文件对象,但没有发现任何类似的东西。有人有什么建议吗?

使用JarInputStream代替JarFile。为了进行测试,将JarInputStream与加载了内存jar数据的ByteArrayInputStream挂钩,并在正常操作中将其与来自文件的输入流挂钩。

File()对象都位于某个文件系统名称空间中。它给了你两个基本的选择:

1)。如果您正在使用带有tempfs文件系统的O/S,那么在那里创建它。2).使用File.createTempFile()并设置delete-on-exit属性。

通常创建子类的方法("public MemoryFile extends File"…)不起作用,因为File()对象不包含执行实际I/O的方法,仅用于保存对象的名称和执行一些文件系统操作。

您需要查看ByteArrayOutputStream和ByteArrayInputStream。这些是Java中内存流对象中的

您可以使用EasyMock来创建类JarFile的模拟对象。对于mock对象,您可以指定在测试中调用哪些方法以及返回值是什么,而不需要在文件系统上实际创建JAR文件。

然后用模拟的JarFile实例调用getTestXml()方法。

它需要一些时间来适应,但你会发现它是值得的。

给定的源代码不能编译,所以这里是一个可编译的版本:

public class JarFileUser {
  public Map<String, Document> getTestXml(JarFile jarFile) throws IOException, ParserConfigurationException, SAXException {
    Map<String, Document> result = new HashMap<String, Document>();
    Enumeration<JarEntry> jarEntries = jarFile.entries();
    while (jarEntries.hasMoreElements()) {
      JarEntry jarEntry = jarEntries.nextElement();
      String name = jarEntry.getName();
      if (name.endsWith(".class") && !name.contains("$")) {
        String testClassName = name.replace(".class", "").replace("/", ".");
        String testXmlFilename = "TEST-" + testClassName + ".xml";
        InputStream testXmlInputStream = jarFile.getInputStream(jarFile.getJarEntry(testXmlFilename));
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        Document testXmlDocument = documentBuilder.parse(testXmlInputStream);
        result.put(testClassName, testXmlDocument);
      }
    }
    return result;
  }
}

下面是使用EasyMock的测试:

public class JarFileUserTest {
  private JarFile mockJarFile;
  private Enumeration<JarEntry> mockJarEntries;
  private JarFileUser jarFileUser;
  private JarEntry first;
  private JarEntry second;
  private JarEntry firstXml;
  @Before
  public void setUp() throws Exception {
    jarFileUser = new JarFileUser();
    // Create a mock for the JarFile parameter
    mockJarFile = createMock(JarFile.class);
    // User Vector to provide an Enumeration of JarEntry-Instances 
    Vector<JarEntry> entries = new Vector<JarEntry>();
    first = createMock(JarEntry.class);
    second = createMock(JarEntry.class);
    entries.add(first);
    entries.add(second);
    expect(first.getName()).andReturn("mocktest.JarFileUser.class");
    expect(second.getName()).andReturn("mocktest.Ignore$Me.class");
    mockJarEntries = entries.elements();
    expect(mockJarFile.entries()).andReturn(mockJarEntries);
    // JarEntry for the XML file
    firstXml = createMock(JarEntry.class);
    expect(mockJarFile.getJarEntry("TEST-mocktest.JarFileUser.xml")).andReturn(firstXml);
    // XML contents
    ByteArrayInputStream is = new ByteArrayInputStream("<test>This is a test.</test>".getBytes("UTF-8"));
    expect(mockJarFile.getInputStream(firstXml)).andReturn(is);
    replay(mockJarFile);
    replay(first);
    replay(second);
    replay(firstXml);
  }
  @Test
  public void testGetTestXml() throws IOException, ParserConfigurationException, SAXException {
    Map<String, Document> map = jarFileUser.getTestXml(mockJarFile);
    verify(mockJarFile);
    verify(first);
    verify(second);
    verify(firstXml);
    assertEquals(1, map.size());
    Document doc = map.get("mocktest.JarFileUser");
    assertNotNull(doc);
    final Element root = (Element) doc.getDocumentElement();
    assertNotNull(root);
    assertEquals("test", root.getNodeName());
    assertEquals("This is a test.", root.getTextContent());
  }
}

关于附加库的说明JarFile是一个类,而不是一个接口,所以根据EasyMock安装文档,你应该在你的类路径中有Objenesis和cglib。

最新更新