s3 bucket state isn't persisting as I expect
I'm primarily referencing this Class Decorator piece of documentation. This leads me to believe that state created or modified in setUp(self): will persist through tests. I run that code and it looks great.
Please let me know if this is a fundamental Python or unittest misunderstanding, but here is my snippet:
import unittest
import boto3
from moto import mock_s3
@mock_s3
class TestMotoBugBaseClass:
def setUp(self):
client = boto3.client("s3")
client.create_bucket(Bucket="test_bucket")
num_buckets = len(
[bucket.name for bucket in boto3.resource("s3").buckets.all()]
)
self.assertEqual(num_buckets, 1) # Looks like we have a bucket!
def test_bug(self):
num_buckets = len(
[bucket.name for bucket in boto3.resource("s3").buckets.all()]
)
self.assertEqual(num_buckets, 1)
class TestInheritingClass(TestMotoBugBaseClass, unittest.TestCase):
pass
Expected: I expect that the bucket we create as part of the setUp method will persist into the test_bug method.
Actual: This test fails - we see 0 buckets returned during execution of test_bug.
Version: I have tried this in both 1.3.14 and the most recent 3.1.1 with similar results.
Thank you for any guidance! Appreciate working with moto so far, slightly confused on by this particular behavior.
Hi @BenjaminCaffrey, welcome to Moto! It does work like this, by extending the BaseClass with the unittest.TestCase-class:
@mock_s3
class TestMotoBugBaseClass(unittest.TestCase):
...
Note that executing the TestMotoBugBaseClass-class also fails in this non-Moto example, because the setUp-method is not only executed for classes that extend unittest.TestCase.
class TestMotoBugBaseClass:
def setUp(self):
self.x = True
def test_bug(self):
print(self.x)
class TestInheritingClass(TestMotoBugBaseClass, unittest.TestCase):
pass
Having said that, looking at your example, running TestInheritingClass should pass, as this does extend the unittest.TestCase. I'll do some debugging to see why this fails.
Thank you @bblommers ! Let me know if there's anything I can do to help.
To clarify my understanding of the situation:
In your snippet, if we were to run python -m unittest on the file, we run TestInheritingClass (because it inherits from unittest.TestCase, which will call setUp and subsequently test_bug (because it also inherits from TestMotoBugBaseClass, and we see that self.x = True. So in that case test_bug is sort of "state aware" of what happened in SetUp.
But when we do the same thing with moto and mocked boto3 state (the snippet I posted), it doesn't seem to be the case.
Yes, that is correct.
The class-decorator is responsible for resetting the state between tests. On basic classes, it will reset before every test-method. If the class extends unittest.TestCase, it will reset the state before the setUp-method instead.
The underlying issue is that the class-decorator acts on compile-time. The only context we have at that point, is that we are extending TestMotoBugBaseClass - but Moto doesn't know that we will be extending TestCase.
It may be possible to change the implementation, so that we figure this out at run-time. At run-time we do know whether we are extending TestCase. Considering that there is a workaround, and the potential to introduce other bugs, I'm going to consider this low-priority though.
Hi @bblommers !
Have you had any time to look into this since this issue was last updated ? :)
Not really @Seluj78 - I haven't found a good solution to this problem yet
I understand. For now I guess I will have to decorate each class individually :/
Although if you do find any idea on how to solve this, I'd love to hear it! I am certain it would be a really appreciated feature for unit test users 😉