Java 如何创建内存中的JAR文件?

Java 如何创建内存中的JAR文件?,java,unit-testing,jar,in-memory,Java,Unit Testing,Jar,In Memory,我正在尝试编写一个函数,如: public Map<String, Document> getTestXml(JarFile jarFile) { Map<String, Document> result = Maps.newHashMap(); Enumeration<JarEntry> jarEntries = jarFile.getEntries(); while (jarEntries.hasMoreElements()) {

我正在尝试编写一个函数,如:

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;
}
publicmap getTestXml(JarFile-JarFile){
Map result=Maps.newHashMap();
枚举jarEntries=jarFile.getEntries();
while(jarEntries.hasMoreElements()){
JarEntry JarEntry=jarEntries.nextElement();
String name=jarEntry.getName();
if(name.endsWith(“.class”)&&!name.contains($”){
字符串testClassName=name.replace(“.class”,”).replace(“/”,”);
字符串testXmlFilename=“TEST-”+testClassName+“.xml”;
InputStream testXmlInputStream=testJarFile.getInputStream(
getJarEntry(testXmlFilename));
DocumentBuilderFactory DocumentBuilderFactory=DocumentBuilderFactory.newInstance();
DocumentBuilder DocumentBuilder=documentBuilderFactory.newDocumentBuilder();
Document testXmlDocument=documentBuilder.parse(testXmlInputStream);
put(testClassName,testXmlDocument);
}
}
返回结果;
}
我想写一个单元测试,它实际上不会在文件系统上创建JAR文件。我试图寻找如何在内存中创建文件对象,但没有找到类似的方法。有人有什么建议吗?

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

然后用mock 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;
  }
}
公共类JarFileUser{
公共映射getTestXml(JarFile JarFile)引发IOException、ParserConfiguration异常、SAXException{
映射结果=新的HashMap();
枚举jarEntries=jarFile.entries();
while(jarEntries.hasMoreElements()){
JarEntry JarEntry=jarEntries.nextElement();
String name=jarEntry.getName();
if(name.endsWith(“.class”)&&!name.contains($”){
字符串testClassName=name.replace(“.class”,”).replace(“/”,”);
字符串testXmlFilename=“TEST-”+testClassName+“.xml”;
InputStream testXmlInputStream=jarFile.getInputStream(jarFile.getJarEntry(testXmlFilename));
DocumentBuilderFactory DocumentBuilderFactory=DocumentBuilderFactory.newInstance();
DocumentBuilder DocumentBuilder=documentBuilderFactory.newDocumentBuilder();
Document testXmlDocument=documentBuilder.parse(testXmlInputStream);
put(testClassName,testXmlDocument);
}
}
返回结果;
}
}
下面是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());
  }

}
public类JarFileUserTest{
私有JarFile mockJarFile;
私有枚举项;
私有JarFileUser JarFileUser;
私人进入优先;
第二,私人市场;
私有JARXML;
@以前
public void setUp()引发异常{
jarFileUser=新的jarFileUser();
//为JarFile参数创建一个模拟
mockJarFile=createMock(JarFile.class);
//用户向量以提供JarEntry实例的枚举
向量项=新向量();
first=createMock(JarEntry.class);
second=createMock(JarEntry.class);
条目。添加(第一);
条目。添加(第二);
expect(first.getName()).andReturn(“mocktest.JarFileUser.class”);
expect(second.getName()).andReturn(“mocktest.Ignore$Me.class”);
mockJarEntries=entries.elements();
expect(mockJarFile.entries()).andReturn(mockJarEntries);
//XML文件的JarEntry
firstXml=createMock(JarEntry.class);
expect(mockJarFile.getJarEntry(“TEST mocktest.JarFileUser.xml”)).andReturn(firstXml);
//XML内容
ByteArrayInputStream is=新的ByteArrayInputStream(“这是一个测试。”.getBytes(“UTF-8”);
expect(mockJarFile.getInputStream(firstXml)).andReturn(is);
重播(mockjar文件);
重播(第一);
重播(秒);
回放(firstXml);
}
@试验
public void testGetTestXml()引发IOException、ParserConfiguration异常、SAXException{
Map Map=jarFileUser.getTestXml(mockJarFile);
验证(文件);
核实(第一);
核实(第二);
验证(firstXml);
assertEquals(1,map.size());
Document doc=map.get(“mocktest.JarFileUser”);
资产不为空(doc);
最终元素根=(元素)doc.getDocumentElement();
assertNotNull(根);
assertEquals(“test”,root.getNodeName());
assertEquals(“这是一个测试。”,root.getTextContent());
}
}
关于附加库的说明
JarFile是一个类,而不是一个接口,因此根据您应该拥有的和类路径中的属性,使用JarInputStream代替JarFile。为了进行测试,将JarInputStream挂接到一个加载了内存中jar数据的ByteArrayInputStream,并在正常操作中将其挂接到文件中的输入流。

您需要查看和。这些是Java中的内存流对象。使用这些,任何东西都不会写入磁盘。

File()对象都位于某个文件系统名称空间内。这为您提供了两个基本选择:

1) 。如果您正在使用带有tempfs文件系统的O/S,请在那里创建它。 2). 使用File.createTempFile()并设置“退出时删除”属性


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

我目前正在使用JMockit。当我尝试模拟JarFile时,我在线程“main”java.lang.NoClassDefFoundError:org/junit/internal/runners/model/MultipleFailureException中得到:Exception您确定EasyMock能够处理JarFile吗?关于JarInputStre