Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stub method when using Flask LiveServerTestCase #107

Open
martijnversluis opened this issue Apr 3, 2017 · 2 comments
Open

Stub method when using Flask LiveServerTestCase #107

martijnversluis opened this issue Apr 3, 2017 · 2 comments

Comments

@martijnversluis
Copy link

We're trying to test a frontend feature that sends a request to a Third Party API when a button is clicked. The click will trigger an internal API call to our Flask application, which will translate this to a request for the ThirdPartyApi.

We try to test this using Splinter, Flask Testing and PhantomJS. Because we don't want to hit the actual API, we want to stub out the method that will perform this request. However, the stub doesn't seem to work and the actual http call is performed. We suspect it has something to do with the difference between the test context and the app context, but we were not able to solve it with the app_context() provided by Flask.

Do you have suggestions how to fix this? Below is a simplified version of the test code we are using.

from splinter import Browser
from flask_testing import LiveServerTestCase
from unittest.mock import patch


class ClickButtonTest(LiveServerTestCase):
    def test_click_button(self):
        browser = Browser('phantomjs')

        browser.visit(self.get_server_url() + "/")

        with self.app.app_context():
            @patch("app.lib.ThirdPartyApi")
            class FakeThirdPartyApi:
                def some_action(self, param):
                    return True

            browser.find_by_text("Click me!").click()

            assert browser.is_text_present("The button is clicked :)")
@jcomo
Copy link
Collaborator

jcomo commented Apr 8, 2017

Unfortunately using the LiveServerTestCase means that mocking will have no effect. The app object is being deployed via the run() method and can't be modified once it has been run. You can think about this like if you ran the development server -- changes that you make to the code don't take effect (unless you're using the reloader which is a different mechanism entirely) until re-running it.

In general its better to use the regular TestCase with the fake client if you are planning on mocking. In your case it doesn't seem like that is possible. However, there are a couple of solutions that I can think of depending on what the rest of that code looks like

  1. When you create your ThirdPartyApi use the configuration environment to determine whether to instantiate the real one or some fake one (whatever that fake implementation looks like)
  2. I don't recommend this method, but it is possible: in the create_app method, you can monkey patch the third party api if it is attached to app via a property (eg. app.third_party_api) and set it to a new implementation

Does that help?

@ProLoDs
Copy link

ProLoDs commented Jan 14, 2019

you can patch at the time when the LiveServer is created:

    @patch("util.ldapClient.LDAPCLient.connect")
    @patch("util.ldapClient.LDAPCLient.login")
    @patch("...")
    @patch("...")
    @patch("...")
    @patch("...")
    def __call__(self, result, *mocklist):
        """
        Override the __call__ to patch the connect and login out
        """
        for lmock in mocklist:
            if '_mock_name' in lmock.__dict__:
                self.mocks[lmock.__dict__['_mock_name']] = lmock

        super(FrontendTest, self).__call__(result=result)

the expect_called() and other functions wont work tho...

Good luck

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants