I have a simple python function that needs tested that looks like this:
# Get columns from BigQuery table def get_schema_for_table(bq_client, source, schema, table): bq_table = bq_client.get_table(f'{source}.{schema}.{table}') return bq_table.schema
However, to test this, I don’t want to test with a real table – I would like to create a Mock schema within my test (and a mock client too).
My test currently looks like this:
def test_get_schema_for_table(mocker): mock_client = mocker.patch('google.cloud.bigquery.Client', autospec=True) Table.schema = MagicMock(return_value=[ SchemaField('column_1', 'STRING', 'NULLABLE', None, (), None), SchemaField('column_2', 'STRING', 'NULLABLE', None, (), None), SchemaField('column_3', 'STRING', 'NULLABLE', None, (), None) ]) source = 'project' schema_name = 'dataset' table_name = 'existing_table' expected_schema = [SchemaField('column_1', 'STRING', 'NULLABLE', None, (), None), SchemaField('column_2', 'STRING', 'NULLABLE', None, (), None), SchemaField('column_3', 'STRING', 'NULLABLE', None, (), None)] returned_schema = get_schema_for_table(mock_client,source,schema_name,table_name) print(returned_schema) assert returned_schema == expected_schema
However, when I print returned_schema
, I get the following: <MagicMock name='Client.get_table().schema' id='4591155568'>
.
Can anyone advise what I am doing wrong?
Advertisement
Answer
Well, you set the value for Table.schema
but you have already mocked google.cloud.bigquery.Client
. When you access any value on your mock_client you just get another magic mock – but you can define what these mocks should return.
So you need to set the expected return value on your mock_client
directly.
Replace you code with this and it should work (although the test might seem a little pointless at that point)
mock_client.get_table("project.dataset.existing_table").schema = [ SchemaField('column_1', 'STRING', 'NULLABLE', None, (), None), SchemaField('column_2', 'STRING', 'NULLABLE', None, (), None), SchemaField('column_3', 'STRING', 'NULLABLE', None, (), None) ]
Although if you want to test more properties I’d suggest the following approach:
mock_table = mock_client.get_table("project.dataset.existing_table") mock_table.schema = [ SchemaField('column_1', 'STRING', 'NULLABLE', None, (), None), SchemaField('column_2', 'STRING', 'NULLABLE', None, (), None), SchemaField('column_3', 'STRING', 'NULLABLE', None, (), None) ] # you can mock additional properties of your table