我正在使用 Java 为 Pig 编写 UDF。它工作正常,但 Pig 没有给我分离环境的选项。我的 Pig 脚本正在做的是从 IP 地址获取地理位置。
这是我在地理位置部分的代码。
private static final String GEO_DB = "GeoLite2-City.mmdb";
private static final String GEO_FILE = "/geo/" + GEO_DB;
public Map<String, Object> geoData(String ipStr) {
Map<String, Object> geoMap = new HashMap<String, Object>();
DatabaseReader reader = new DatabaseReader.Builder(new File(GEO_DB)).build();
// other stuff
}
GeoLite2-City.mmdb
存在于 HDFS 中,这就是为什么我可以使用 /geo/GeoLite2-City.mmdb
从绝对路径引用。
但是,我不能通过我的 JUnit 测试做到这一点,或者我必须在我的本地机器和 Jenkins 上创建 /geo/GeoLite2-City.mmdb
,这并不理想。我正在尝试找出一种方法让我的测试通过,同时使用 new File(GEO_DB)
而不是
getClass().getResourceAsStream('./geo/GeoLite2-City.mmdb')
因为
getClass().getResourceAsStream('./geo/GeoLite2-City.mmdb')
在 Hadoop 中不起作用。
如果我运行 Junit 测试,它会失败,因为我的本地计算机上没有 /geo/GeoLite2-City.mmdb
。
无论如何我可以克服这个问题吗?我只是希望我的测试通过而不更改使用 getClass().getResourceAsStream
的代码,我不能 if/else 解决这个问题,因为 Pig 没有给我一种方法来传递参数或也许我遗漏了什么。
这是我的 JUnit 测试
@Test
@Ignore
public void shouldGetGeoData() throws Exception {
String ipTest = "128.101.101.101";
Map<String, Object> geoJson = new LogLine2Json().geoData(ipTest);
assertThat(geoJson.get("lLa").toString(), is(equalTo("44.9759")));
assertThat(geoJson.get("lLo").toString(), is(equalTo("-93.2166")));
}
如果我从资源文件夹中读取数据库文件,它会起作用。这就是为什么我有@Ignore
最佳答案
此外,您的整个代码看起来都无法测试。
每次在生产代码中直接调用 new 时,都可以防止依赖注入(inject);从而使测试代码变得更加困难。
重点是不要在生产代码中调用 new File()
。
相反,您可以使用为您提供“随时可用”的 DatabaseReader 对象的工厂。然后你可以测试你的工厂做正确的事;并且您可以在测试此代码时模拟该工厂(以返回模拟的数据库读取器)。
因此,一个文件实例只是您此处“测试问题”的首要问题。
老实说:不要先编写生产代码。做TDD:先写测试用例;您很快就会了解到,您在此处展示的此类生产代码确实很难测试。当您应用 TDD 时,您从“测试角度”开始,您将创建真正可测试的生产代码。
关于java - 如何在 Java 项目中包含一个资源文件以仅与 new File() 一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36781391/