gpt4 book ai didi

Python Mock 没有被分配给类(class)

转载 作者:行者123 更新时间:2023-12-01 09:02:45 24 4
gpt4 key购买 nike

我有我的Python类(class)

class FetchData:

def __init__(self, spark):
self.spark = spark

def filter_data_from_s3(self, table_name, s3_location, sql_query, table_schema, partition_column):

# DO SOMETHING

调用此类的另一个文件是 FilterData.py

from accessor.FetchData import FetchData
from pyspark.sql import SparkSession


import sys


def main(args):
spark = SparkSession \
.builder \
.appName("ROAD") \
.config(conf=sparkConf) \
.getOrCreate()
try:
args_map = DataUtils.parse_args(args)
logger.info("Parsed Argument Map for Filtering Data : {}".format(args_map))
f = FetchData(spark)

for table in table_list:
table_name = table.get("table_name")
s3_location = table.get("s3_location")
sql_query = DataUtils.un_parametrize(table.get("sql_query"), args_map)
table_schema = table.get("table_schema", args)
f.filter_data_from_s3(table_name=table_name,
s3_location=s3_location,
sql_query=sql_query,
table_schema=table_schema,
partition_column=args_map.get('partition_column'))
finally:
spark.stop()


if __name__ == "__main__":
main(sys.argv)

我编写了一个测试用例来测试filterData.py main函数我想模拟 filter_data_from_s3 调用。

这是我编写的测试用例 -

class TestFilterData(unittest.TestCase):

@patch('accessor.FetchData')
def test_main_call_times_for_na(self, fetch_data_mock):
print(fetch_data_mock)
spark_session = get_spark_session()
CUSTOMER_ACCESS_SCHEMA = StructType(
[StructField('enc_customer_id', StringType(), False),
StructField('marketplace_id', IntegerType(), False)]
)
df = spark_session.createDataFrame([
("customerid1", 1),
("customerid1", 2),
("customerid2", 2)
], CUSTOMER_ACCESS_SCHEMA)

fetch_data_mock.filter_data_from_s3.return_value = df
test_args = ["", "--run_date=2018-09-01", "--num_days=730",
"--region=NA", "--marketplace_id=1", "--region_id=1", "--num_asins=1000"]
FilterData.main(test_args)


if __name__ == '__main__':
unittest.main()

当我调用我的测试用例时,它实际上调用了过滤数据并失败。相反,我希望调用我的模拟方法。我是 python 新手,现在面临这个问题大约一天了。谁能告诉我我在这里做错了什么。

最佳答案

如果您正在从 filterData.py 测试 main(),那么您应该在 filterData.py< 中模拟 FetchData/。也就是说,它应该是 @patch('filterData.FetchData')

,而不是 @patch('accessor.FetchData')

始终在使用对象的地方模拟对象,而不是它们源自的地方。

您遇到的问题是,即使您正在修补符号 accessor.FetchData 以指向不同的对象(模拟),在测试中应用该指令时,被测试的模块 filterData 已经将引用导入到其命名空间中的原始对象。现在,您已将原始模块的 FetchData 符号更改为其他内容,这并不重要,它不会影响 filterData 的命名空间。如果您希望 filterData 丢失原始引用并指向您的模拟,则必须将其自己的 FetchData 符号指向该模拟。

编辑

根据您的代码使用 FetchData 的方式,这就是我为您正在寻找的内省(introspection)类型设置模拟的方式。

import mock

@mock.patch('filterData.FetchData')
def test_main_call_times_for_na(self, fetch_data_mock):
spark_session = get_spark_session()
CUSTOMER_ACCESS_SCHEMA = StructType(
[StructField('enc_customer_id', StringType(), False),
StructField('marketplace_id', IntegerType(), False)]
)
df = spark_session.createDataFrame([
("customerid1", 1),
("customerid1", 2),
("customerid2", 2)
], CUSTOMER_ACCESS_SCHEMA)
fake_f = mock.Mock()
fake_f.filter_data_from_s3.return_value = df
# ensuring that I also control the instance returned by filterData.FetchData
fetch_data_mock.return_value = fake_f

test_args = ["", "--run_date=2018-09-01", "--num_days=730",
"--region=NA", "--marketplace_id=1", "--region_id=1", "--num_asins=1000"]
FilterData.main(test_args)

assert fake_f.filter_data_from_s3.call_count==11

关于Python Mock 没有被分配给类(class),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52342533/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com