我有我的python课

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主要功能
我想模拟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的新手,现在大约一天都面临这个问题。谁能告诉我我在做什么错。

最佳答案

如果要从main()测试filterData.py,则应该在FetchData中模拟filterData.py。也就是说,应将@patch('accessor.FetchData')代替@patch('filterData.FetchData')

总是在使用对象时对其进行嘲笑,而不是在其起源处进行嘲笑。

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

编辑

根据您的代码使用FetchData的方式,这就是我要为所需的自省类型设置模拟程序的方式。

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 - 没有为类分配Python Mock,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52342533/

10-09 12:31