如何在Scala中通过Spark模拟DynamoDB访问?

时间:2019-06-26 04:26:11

标签: scala apache-spark amazon-dynamodb scalatest scalamock

我有一个用Scala编写的Spark作业,最终将其写到AWS DynamoDB。我想围绕它编写一些单元测试,但是唯一的问题是我不知道如何模拟写入DynamoDB的位。我正在使用他们的emr-dynamodb-connector类,这意味着我没有使用任何依赖项注入(否则这很容易)。

使用Spark读取一些RDD数据后,我对其进行了一些简单的转换,将其转换为(org.apache.hadoop.io.Text, org.apache.hadoop.dynamodb.DynamoDBItemWritable)类型的Pair RDD。因此,我的代码唯一使用Dynamo的方法是创建DynamoDBItemWritable对象。该类本身不包含任何逻辑来利用AWS开发工具包(SDK)保存任何内容。它本质上只是一个数据对象。然后我的代码将其调用:

val conf = new Configuration()
conf.set("dynamodb.servicename", "dynamodb")
conf.set("dynamodb.input.tableName", "MyOutputTable")
conf.set("dynamodb.output.tableName", "MyInputTable")
conf.set("dynamodb.endpoint", "https://dynamodb.us-east-1.amazonaws.com")
conf.set("dynamodb.regionid", "us-east-1")
conf.set("mapred.output.format.class", "org.apache.hadoop.dynamodb.write.DynamoDBOutputFormat")
conf.set("mapred.input.format.class", "org.apache.hadoop.dynamodb.read.DynamoDBInputFormat")
myTransformedRdd.saveAsHadoopDataset(new JobConf(conf)

...并且连接器神奇地注册了正确的类并进行了正确的调用,从而有效地将结果相应地保存到DynamoDB。

我无法模拟SparkSession,因为它有一个私有的构造函数(无论如何还是很混乱的)。据我所知,我没有任何直接方法来模拟DynamoDB客户端。 Scala(或Scalatest或Scalamock)中是否有一些魔术语法可以让我告诉它,如果它想实例化Dynamo客户端类,则应改用模拟版本?

如果没有,我将如何测试此代码?从理论上讲,我想也许有一种方法可以建立一个本地的Dynamo内存实例,然后更改dynamodb.endpoint的值,但这听起来很混乱,只是为了使单元测试正常工作。另外,我不确定还是有可能。

1 个答案:

答案 0 :(得分:0)

看看LocalStack。它提供了一个易于使用的测试/模拟框架,用于通过在本地计算机或Docker中扩展与AWS兼容的API来开发与AWS相关的应用程序。它支持两打AWS API,其中包括DynamoDB。确实是功能测试的绝佳工具,无需为此在AWS中使用单独的环境。

如果仅需要DynamoDB,则还有另一种工具:DynamoDB LocalDocker image,板载Amazon DynamoDB。

两者都像启动Docker容器一样简单:

docker run -p 8000:8000 amazon/dynamodb-local
docker run -P localstack/localstack

如果您使用JUnit 5进行测试,让我向您推荐JUnit 5 extensions for AWS,这是一些JUnit 5扩展,可用于测试与AWS相关的代码。这些扩展可用于为由诸如localstack(或实际)之类的工具提供的AWS服务客户端注入客户端。 AWS Java SDK v 2.x和v 1.x均受支持。