python-3.x 如何用Moto3模拟Athena查询结果值用于特定的表?

ctehm74n  于 2023-02-06  发布在  Python
关注(0)|答案(2)|浏览(103)

我使用pytestmoto3来测试类似于以下代码的一些代码:

response = athena_client.start_query_execution(
        QueryString='SELECT * FROM xyz',
        QueryExecutionContext={'Database': myDb},
        ResultConfiguration={'OutputLocation': someLocation},
        WorkGroup=myWG
    )

execution_id = response['QueryExecutionId']

if response['QueryExecution']['Status']['State'] == 'SUCCEEDED':
    response = athena_client.get_query_results(
        QueryExecutionId=execution_id
    )

    results = response['ResultSet']['Rows']
    ...etc

在我的测试中,我需要results = response['ResultSet']['Rows']的值由测试控制。我使用了如下代码:

backend = athena_backends[DEFAULT_ACCOUNT_ID]["us-east-1"]
    rows = [{"Data": [{"VarCharValue": "xyz"}]}, {"Data": [{"VarCharValue": ...}, etc]}]
    column_info = [
        {
            "CatalogName": "string",
            "SchemaName": "string",
            "TableName": "xyz",
            "Name": "string",
            "Label": "string",
            "Type": "string",
            "Precision": 123,
            "Scale": 123,
            "Nullable": "NOT_NULL",
            "CaseSensitive": True,
        }
    ]
    results = QueryResults(rows=rows, column_info=column_info)
    backend.query_results[NEEDED_QUERY_EXECUTION_ID] = results

但是那是不起作用的,因为我猜NEEDED_QUERY_EXECUTION_ID之前从测试中是不知道的。我怎么控制它呢?

  • 更新 *

根据建议,我尝试使用:

results = QueryResults(rows=rows, column_info=column_info)
d = defaultdict(lambda: results.to_dict())
backend.query_results = d

强制返回值,但它似乎不工作,因为从moto3models.AthenaBackend.get_query_results,我有这样的代码:

results = (
        self.query_results[exec_id]
        if exec_id in self.query_results
        else QueryResults(rows=[], column_info=[])
    )
    return results

这将失败,因为if条件不满足。

waxmsbnn

waxmsbnn1#

扩展defaultdict的解决方案,您可以创建一个包含所有execution_ids的自定义字典,并且始终返回相同的对象:

class QueryDict(dict):
    def __contains__(self, item):
        return True
     def __getitem__(self, item):
        rows = [{"Data": [{"VarCharValue": "xyz"}]}, {"Data": [{"VarCharValue": "..."}]}]
        column_info = [
            {
                "CatalogName": "string",
                "SchemaName": "string",
                "TableName": "xyz",
                "Name": "string",
                "Label": "string",
                "Type": "string",
                "Precision": 123,
                "Scale": 123,
                "Nullable": "NOT_NULL",
                "CaseSensitive": True,
            }
        ]
        return QueryResults(rows=rows, column_info=column_info)

backend = athena_backends[DEFAULT_ACCOUNT_ID]["us-east-1"]

backend.query_results = QueryDict()
oug3syen

oug3syen2#

使用自定义词典的另一种解决方案是seed Moto。
播种Moto确保它总是生成相同的“随机”标识符,这意味着您总是知道NEEDED_QUERY_EXECUTION_ID的值将是什么。

backend = athena_backends[DEFAULT_ACCOUNT_ID]["us-east-1"]
rows = [{"Data": [{"VarCharValue": "xyz"}]}, {"Data": [{"VarCharValue": "..."}]}]
column_info = [...]
results = QueryResults(rows=rows, column_info=column_info)
backend.query_results["bdd640fb-0667-4ad1-9c80-317fa3b1799d"] = results

import requests
requests.post("http://motoapi.amazonaws.com/moto-api/seed?a=42")

# Test - the execution id will always be the same because we just seeded Moto

execution_id = athena_client.start_query_execution(...)

有关接种Moto的文档可在此处找到:http://docs.getmoto.org/en/latest/docs/configuration/recorder/index.html#deterministic-identifiers(它只讨论了在记录/重放请求的上下文中播种Moto,但该功能可以单独使用。)

相关问题