dbt-labs / dbt-labs/dbt

[Feature] Allow macro overrides in unit tests for nested macros

Open
#12,165 1 comment 0 reactions 0 assignees View on GitHub
engine:v1 status:triage type:feature unit tests
Dominant language
Rust
Stars
13.8k
Forks
2.6k
Avg merge
21h 31m
Merged PRs (30d)
56

Description

### Is this a new bug in dbt-core?

- [x] I believe this is a new bug in dbt-core
- [x] I have searched the existing issues, and I could not find an existing issue for this bug

### Current Behavior

If a macro (outermost) references another macro (innermost) for which an override in a unit test is set, it won't use the override value. I can't override the outermost macro because I call it twice in my dbt model with different arguments and expecting different result sets. You can't override multiple macro calls of the same macro in a unit test.

Unit test setup:
```
- name: unit_test_A
model: some_model
overrides:
macros:
get_config: >
{
'attributes': [
{'attribute': 'attribute_A', 'data_type': 'VARCHAR', 'tools': ['tool_A']},
{'attribute': 'attribute_B', 'data_type': 'INTEGER', 'tools': ['tool_A', 'tool_B']}
],
'tools': ['tool_A', 'tool_B']
}
```
The unit test also overrides all the `ref` relations in `some_model`.

This is the macro that is being overridden. It returns a JSON object with two key-value pairs. The first one's value is a list of JSON objects and the second is a list of strings.
```
{% macro get_config(filter_type, filter_value=none) %}

< do stuff >

---------- Return JSON object ----------
{{ return({
'attributes': [],
'tools': []
}) }}

{% endmacro %}
```

The macro above is called in the one below. The result of `get_config` in this macro doesn't return the override value set in the unit test. Furthermore, it returns no results (see compiled code example below).
```
{% macro select_columns(filter_type, filter_value) %}

---------- Get filtered attributes ----------
{% set config = get_config(filter_type, filter_value) %}
{% set attributes = config['attributes'] %}

{%- for attr in attributes %}
CAST({{ attr['attribute'] }} AS {{ attr['data_type'] }}) AS {{ attr['attribute'] }},
{%- endfor %}

{% endmacro %}
```

Macro used in dbt model:
```
SELECT
user_id,
{{ select_columns('source', 'some_model') }}
FROM {{ ref('some_model') }}
```

Actual unit test compiled code:
```
SELECT
user_id,

---------- Get filtered attributes ----------

FROM __dbt__cte__some_model
```

### Expected Behavior

The result of `get_config` in the `get_columns` macro should be the override value.

Expected compiled code:
```
SELECT
user_id,

---------- Get filtered attributes ----------
attribute_A,
attribute_B,

FROM __dbt__cte__some_model
```

### Steps To Reproduce

1. Create two macros where one references the results of the other
2. Call the outermost macro in a dbt model
3. Create a unit test where you override the return value of the innermost macro
4. Run the unit test
5. Check the compiled code to see no results returned from the outermost macro

### Relevant log output

```shell

```

### Environment

```markdown
- OS: macOS 26.1
- Python: 3.10.18
- dbt: 1.9.4
```

### Which database adapter are you using with dbt?

snowflake

### Additional Context

This would be solved if we could override multiple calls to the same macro in a unit test.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.