Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 检索路径以处理测试期间出现问题的文件_Java_Eclipse_Testing_Ant_Powermock - Fatal编程技术网

Java 检索路径以处理测试期间出现问题的文件

Java 检索路径以处理测试期间出现问题的文件,java,eclipse,testing,ant,powermock,Java,Eclipse,Testing,Ant,Powermock,我正在为我的程序开发Ant builder,特别是处理文件路径 我找到了一个非常简单的解决方案,只需在常量界面中添加两个字段: /** The actual jar file where the class is run */ public static final File JAR_FILE = new File(MagicHogwarts.class.getProtectionDomain().getCodeSource().getLocation().getPath()); /** Th

我正在为我的程序开发Ant builder,特别是处理文件路径

我找到了一个非常简单的解决方案,只需在常量界面中添加两个字段:

/** The actual jar file where the class is run */
public static final File JAR_FILE = new File(MagicHogwarts.class.getProtectionDomain().getCodeSource().getLocation().getPath());

/** The path to the main folder where the file .jar is run */
public static final String BASE_DIRECTORY = JAR_FILE.getAbsolutePath().replace(JAR_FILE.getName(), "");
在处理文件的每个方法中,我只需询问jar所在主文件夹的相对路径,然后首先添加BASE_目录,至少在运行jar的eclipse中的macOSX中都可以正常工作

很高兴有了这个快速解决方案,我运行了我的测试。那失败了。 问题似乎在Constants接口中,无法创建
JAR\u文件
,因为
getLocation
返回null,然后
getPath
失败

但我不明白为什么

因此,我尝试模拟接口,由于var声明为static final,因此存在明显的问题,因此我尝试使用PowerMock:

@RunWith(PowerMockRunner.class)
@PrepareForTest({GameWindow.class,Constants.class})
public class MapReaderTest {

@Test
public void testReadingExampleMap() throws Exception {
    mockStatic(GameWindow.class);
            mockStatic(Constants.class);
    TextureLoader tl = createMock(TextureLoader.class);
    Texture tx = createMock(Texture.class);
    expect(GameWindow.getTextureLoader()).andReturn(tl);
            expect(Constants.BASE_DIRECTORY).andReturn("/Users/Gianmarco/Documents/java/MagicHogwarts/").anyTimes();
    expect(tl.getTexture("/Users/Gianmarco/Documents/java/MagicHogwarts/bin/mh/test/sewer_tileset.png")).andReturn(tx);
    expect(tx.getImageHeight()).andReturn(32).anyTimes();
    expect(tx.getImageWidth()).andReturn(32).anyTimes();
    replay(GameWindow.class);
            replay(Constants.class);
    replay(tl);
    replay(tx);

    // Act
    Map map = new TMXMapReader().readMap("/bin/mh/test/sewers.tmx");//mapFile.getAbsolutePath());

    // Assert
    assertEquals(Map.ORIENTATION_ORTHOGONAL, map.getOrientation());
    assertEquals(50, map.getHeight());
    assertEquals(50, map.getHeight());
    assertEquals(24, map.getTileWidth());
    assertEquals(24, map.getTileHeight());
    assertEquals(2, map.getLayerCount());
}
}
但我得到了一个ExceptionInInitializerError,常量的第60行,即声明JAR_文件的那一行,该错误是由NullPointerException引起的

我认为下一步是将接口转换为类,也许powermock无法以这种方式处理接口

运行,并得到一个NoClassDefFoundError。 仍然没有结果,我不知道该怎么办。所以我试着反思

我使用了这种静态方法:

static void setFinalStatic(Field field, Object newValue) throws Exception {
    field.setAccessible(true);

    // remove final modifier from field
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

    field.set(null, newValue);
}
称之为:

setFinalStatic(Constants.class.getField("JAR_FILE"), null);
setFinalStatic(Constants.class.getField("BASE_DIRECTORY"), "my/path/hardcoded");
但这两种方法都不起作用,我得到了一个ExceptionInInitializerRor,其堆栈包含
sun.mic.Unsafe.EnsureClassified(本机方法)
、sun.reflect和其他内容

我花了几个小时研究这个问题,得出的结论是JAR_文件和用于初始化它的方法有问题,因为即使从常量中删除
final
修饰符,我也无法更改调用
constants.JAR_FILE=null

我解决问题的方法是:

/** The actual jar file where the class is run */
    public static final File    JAR_FILE            = (MagicHogwarts.class.getProtectionDomain().getCodeSource().getLocation() == null ? null : new File(MagicHogwarts.class.getProtectionDomain().getCodeSource().getLocation().getPath()));

    /** The path to the main folder where the file .jar is run */
    public static final String  BASE_DIRECTORY      = (JAR_FILE != null ? JAR_FILE.getAbsolutePath().replace(JAR_FILE.getName(), "") : "/Users/Gianmarco/Documents/java/MagicHogwarts/");
这是使用if语句的一种粗鲁、非常不愉快和可怕的方式

我的问题是,是否有任何不同的方法可以从终端行获取jar的base dir和/或用
#javamyclass
调用的文件,这些方法既可以用于正常处理(也可以是jar),也可以用于测试


我找到的解决方案是可行的,但我不认为将一些测试代码硬编码到类中是一件好事,事实上使用if就像告诉Constants类“如果我正在测试,给我这个模拟字符串,否则给我真正的路径”。如果在正常的程序行为中没有用处,我希望将测试代码与类分开(应该如此)。

测试时不应该依赖绝对路径,因为它会使测试变得脆弱和不可移植

我们应该寻找资源,而不是绝对路径。最好使用Class.getResource或Class.getResourceAsStream进行读取


对于前者,您可以检索URL。如果有必要,可以使用url.toExternalForm将其转换回绝对路径,但一旦您拥有了所需的资源,就应该足够了

您可以通过各种方法获取JAR文件的位置,您已经尝试了一些。这听起来像是在运行测试时,您是针对原始
.class
文件运行的,并且没有JAR文件。寻找一种方法来利用
Class.getResource()
Class.getResourceAsStream()
并在测试类路径上显示所需内容,而不是在磁盘上查找文件。另外,请记住,静态常量字符串是内联的,用于可能发生更改的对象是危险的。