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

Rollback Issue With TestCase #42

Open
seanpar203 opened this issue Dec 24, 2019 · 3 comments
Open

Rollback Issue With TestCase #42

seanpar203 opened this issue Dec 24, 2019 · 3 comments

Comments

@seanpar203
Copy link

Following the documentation of decorating celery tasks with @close_connection, I've had some difficult with running django tests using pytest as the runner.

Here's the code(it's pretty simple)

test.py

    @patch("saleor.payment.models.Subscription.get_detail")
    def test_handle_invoice_payment_succeeded(self, retrieve_mock):
        retrieve_mock.return_value = Mock(
            status="active",
            current_period_end=datetime.now().timestamp(),
            current_period_start=datetime.now().timestamp(),
            cancel_at_period_end=False,
        )

        update_subscription(Events.invoice.payment_succeeded)

        subscription = Subscription.objects.get(
            stripe_id=Events.invoice.payment_succeeded
        )

        self.assertEqual(subscription.status, "active")

tasks.py

@app.task
@close_connection
def update_subscription(sub_id):
    """ Updates a subscription to match what's in Stripe. """
    try:
        subscription = Subscription.objects.get(stripe_id=sub_id)
    except Subscription.DoesNotExist:
        logger.exception("update_subscription_failure")
        return

    try:
        subscription.update()
    except StripeError:
        logger.exception("update_subscription_failure")
    else:
        subscription.save()

When running pytest I get these errors:

self = <django_db_geventpool.backends.postgresql_psycopg2.base.DatabaseWrapper object at 0x7f9f90bb1ac8>, rollback = True

    def set_rollback(self, rollback):
        """
        Set or unset the "needs rollback" flag -- for *advanced use* only.
        """
        if not self.in_atomic_block:
            raise TransactionManagementError(
>               "The rollback flag doesn't work outside of an 'atomic' block.")
E           django.db.transaction.TransactionManagementError: The rollback flag doesn't work outside of an 'atomic' block.

The test also fails but when I paste the task functionality inside the test and don't actually call the task function, the test passes.

Is this expected or am I doing something wrong?

@seanpar203
Copy link
Author

I guess a solution is to create a function that does the work and have the task call that function, that way the function can be tested outside the scope of a task but still have the proper close_connection functionality when in production?

def calculate_money():
    # Do something
    return None

@app.task
@close_connection
def task_calculate_money():
    calculate_money()

Although this isn't ideal obviously.

@jneight
Copy link
Owner

jneight commented Mar 2, 2020

Hi!, Have you tried with any of the others methods in the readme instead of using the decorator?

https://github.com/jneight/django-db-geventpool/blob/master/README.rst#using-orm-when-not-serving-requests

@michalc
Copy link

michalc commented Apr 25, 2020

I had a similar issue when using pytest.mark.django_db. Ultimately, I didn't use close_connection that comes with django-db-geventpool, but rolled my own that only closed the connection if not in a transaction (which pytest.mark.django_db performs tests in). Something that did:

from django.db import connection

if not connection.in_atomic_block:
    connection.close_if_unusable_or_obsolete()

Not great, since I'm not such a fan having code specifically for the reason that it behaves differently in the tests than in production, but it may be the least-bad option.

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