0

I have a streamlit app, for which I'd like to create unit tests. I am unable to mock objects though. I have a foo.py with the following content:

import streamlit as st

def dialog_func():
    result = dummy_func()
    st.write(result)

def dummy_func():
    return 'foo'

dialog_func()

and the following corresponding test_foo.py:

from unittest.mock import patch

from streamlit.testing.v1 import AppTest

def test_foo():
    with patch("foo.dummy_func") as mock_dummy_func:
        mock_dummy_func.return_value ='bar'
        at = AppTest.from_file("foo.py").run()
        assert at.markdown[0].value == 'bar'

Running this shows, that patching the method does not work and 'foo' is returned instead of 'bar':

$ pytest test_foo.py 
...
======================================= short test summary info =======================================
FAILED test_foo.py::test_foo - AssertionError: assert 'foo' == 'bar'
========================================== 1 failed in 0.26s ==========================================

1 Answer 1

1

You can use some form of dependency injection but it might be difficult for real apps other than this trivial example. Notice the use of from_function() instead, so you have the option to inject the mocked functions.

test_foo.py:

from unittest.mock import patch

import foo
import streamlit as st
from streamlit.testing.v1 import AppTest

def test_foo():
    with patch("foo.dummy_func") as mock_dummy_func:
        mock_dummy_func.return_value ='bar'
        at = AppTest.from_function(foo.main, args=(foo.dialog_func, foo.dummy_func)).run()
        assert at.markdown[0].value == 'bar'

and foo.py:

import streamlit as st

def dialog_func():
    result = dummy_func()
    st.write(result)


def dummy_func():
    return 'foo'


def main(dialog_func, dummy_func):
    import streamlit as st
    dialog_func()

main(dialog_func, dummy_func)
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much! I have not tried it on my side yet, but is the modification that you have done to foo.py necessary to make the test case work? Or would the AppTest.from_function(...) approach work with the original foo.py too?
You won't be able to inject the function in the original foo.py

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.