很抱歉又提出一个关于这个普遍问题的问题,但是我在SO上找到的所有问题似乎都与我的问题无关。
我有一个现有的、正在工作的数据流水线,它接受 KV<Long, Iterable<TableRow>>
对象,并输出 TableRow
对象。这段代码在我们的生产环境中运行正常。现在我正在尝试使用直接运行器实现单元测试来测试这个管道,但是当单元测试碰到这行代码时失败了:
LinkedHashMap<String, Object> evt = (LinkedHashMap<String, Object>) row.get(Schema.EVT);
在管道中,抛出错误信息:
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap 无法转换为 java.util.LinkedHashMap
现有数据流代码的简化版本如下:
public static class Process extends DoFn<KV<Long, Iterable<TableRow>>, TableRow> {
/* private variables */
/* constructor */
/* private functions */
@ProcessElement
public void processElement(ProcessContext c) throws InterruptedException, ParseException {
EventProcessor eventProc = new EventProcessor();
Processor.WorkItem workItem = new Processor.WorkItem();
Iterator<TableRow> it = c.element().getValue().iterator();
// process all TableRows having the same id
while (it.hasNext()) {
TableRow item = it.next();
if (item.containsKey(Schema.EVT))
eventProc.process(item, workItem);
else
/* process by different Proc class */
}
/* do additional logic */
/* c.output() is somewhere far below */
}
}
public class EventProcessor extends Processor {
// Extract data from an event into the WorkItem
@SuppressWarnings("unchecked")
@Override
public void process(TableRow row, WorkItem item) {
try {
LinkedHashMap<String, Object> evt = (LinkedHashMap<String, Object>) row.get(Schema.EVT);
LinkedHashMap<String, Object> profile = (LinkedHashMap<String, Object>) row.get(Schema.PROFILE);
/* if no exception, process further business logic */
/* business logic */
} catch (ParseException e) {
System.err.println("Bad row");
}
}
}
准备Process() DoFn
的主要输入的单元测试相关部分如下:
Map<Long, List<TableRow>> groups = new HashMap<Long, List<TableRow>>();
List<KV<Long, Iterable<TableRow>>> collections = new ArrayList<KV<Long,Iterable<TableRow>>>();
Gson gson = new Gson();
// populate the map with events grouped by id
for(int i = 0; i < EVENTS.length; i++) {
TableRow row = gson.fromJson(EVENTS[i], TableRow.class);
Long id = EVENT_IDS[i];
if(groups.containsKey(id))
groups.get(id).add(row);
else
groups.put(id, new ArrayList<TableRow>(Arrays.asList(row)));
}
// prepare main input for pipeline
for(Long key : groups.keySet())
collections.add(KV.of(key, groups.get(key)));
引起问题的代码是
gson.fromJson(EVENTS[i], TableRow.class);
,似乎将TableRow的内部表示形式编码为了错误类型的LinkedTreeMap。TableRow的编码类型似乎是
com.google.gson.internal.LinkedTreeMap
,而不是预期的java.util.LinkedHashMap
。我是否可以将在我的单元测试中创建的TableRow强制转换为正确类型的java.util.LinkedHashMap
,以便在不对已在生产环境中运行的现有数据流代码进行任何更改的情况下使单元测试成功?
LinkedHashMap
强制转换为现有代码已经存在一段时间了。将强制转换更改为Map
会有什么后果吗? - MaxMap
替换LinkedHashMap
即可。这样你就不需要关心API返回的是哪种映射实现了。 - Mick MnemonicLinkedTreeMap
是Map
的子类,那就不应该有问题,除非你使用了该类的特定功能。但我认为你最好的选择是尝试一下,看看是否可行。 - Andrei SfatAbstractMap
,因此它也是一个Map
。如果以下代码没有使用到LinkedHashMap
和HashMap
的特定内容,那么应该是可以的。但当然,我会先进行测试。 请参考:https://github.com/google/gson/blob/master/gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java - Roman Puchkovskiy