【发布时间】:2018-06-10 04:35:57
【问题描述】:
对于就这个一般性问题提出另一个问题,我深表歉意,但我在 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? -
@RomanPuchkovskiy 老实说,我不确定。
LinkedHashMap的演员表是以前某个时候的现有代码。将演员表更改为Map会有什么后果吗? -
没错。针对接口编写代码并将
LinkedHashMap替换为Map。那么你就不需要关心 API 碰巧返回了哪个地图实现。 -
@Max 如果
LinkedTreeMap是Map的孩子,那应该不是问题,除非您使用该类的特定内容。但我认为你最好的选择是尝试看看它是否有效
标签: java google-cloud-dataflow apache-beam dataflow