使用 s3fs(通过 dask)测试模拟 S3 存储桶的行为是意外的
Testing behavior of a mocked S3 bucket using s3fs (by dask) is unexpected
我有一个简单的功能,可以将文件添加到基本 S3 位置。基本位置作为环境变量给出:
os.environ["TEST_BASE"] = "my-bucket/testing/"
函数是:
def add_file(file):
print(f"In function: {os.getenv('TEST_BASE')}")
s3 = s3fs.S3FileSystem()
s3.touch(os.getenv('TEST_BASE') + file)
print("In function: " + str(s3.ls(os.getenv('TEST_BASE'))))
现在,我想测试它的行为:
with mock_s3():
with unittest.mock.patch.dict(os.environ, {"TEST_BASE": "foo/bar/"}):
print(f"TEST_BASE = {os.getenv('TEST_BASE')}")
s3_conn = boto3.client('s3', 'us-west-2')
s3_conn.create_bucket(Bucket='foo')
s3 = s3fs.S3FileSystem()
s3.touch(os.getenv('TEST_BASE') + 'yoo')
print(s3.ls(os.getenv("TEST_BASE")))
add_file('goo')
print(s3.exists(os.getenv("TEST_BASE") + 'goo')) # (*)
print(s3.ls(os.getenv("TEST_BASE"))) # (**)
print(f"TEST_BASE = {os.getenv('TEST_BASE')}")
现在,我无法理解的部分是 (*)
打印 True
但是 (**)
仅列出一个对象(yoo
).这是怎么回事?
可能发生的情况是 mock_s3
函数中的 s3
对象出于性能原因正在缓存目录列表。您使用单独的实例创建新的空文件,因此外部实例不知道任何内容已更改。尝试在 add_file
和 s3.ls
之间插入 s3.invalidate_cache()
。
在 unittest
ing 的上下文中,我得到了以下 setUp
和 teadDown
:
def setUp(self):
self.mock_s3.start()
s3_conn = boto3.client('s3', 'us-west-2')
s3_conn.create_bucket(Bucket='bucket')
self.s3 = s3fs.S3FileSystem()
def tearDown(self):
self.mock_s3.stop()
并避免了装饰器的使用。这对问题中描述的案例没有直接帮助,但是,由于这个用例对我来说是个问题,所以我把它放在这里以供参考。
我有一个简单的功能,可以将文件添加到基本 S3 位置。基本位置作为环境变量给出:
os.environ["TEST_BASE"] = "my-bucket/testing/"
函数是:
def add_file(file):
print(f"In function: {os.getenv('TEST_BASE')}")
s3 = s3fs.S3FileSystem()
s3.touch(os.getenv('TEST_BASE') + file)
print("In function: " + str(s3.ls(os.getenv('TEST_BASE'))))
现在,我想测试它的行为:
with mock_s3():
with unittest.mock.patch.dict(os.environ, {"TEST_BASE": "foo/bar/"}):
print(f"TEST_BASE = {os.getenv('TEST_BASE')}")
s3_conn = boto3.client('s3', 'us-west-2')
s3_conn.create_bucket(Bucket='foo')
s3 = s3fs.S3FileSystem()
s3.touch(os.getenv('TEST_BASE') + 'yoo')
print(s3.ls(os.getenv("TEST_BASE")))
add_file('goo')
print(s3.exists(os.getenv("TEST_BASE") + 'goo')) # (*)
print(s3.ls(os.getenv("TEST_BASE"))) # (**)
print(f"TEST_BASE = {os.getenv('TEST_BASE')}")
现在,我无法理解的部分是 (*)
打印 True
但是 (**)
仅列出一个对象(yoo
).这是怎么回事?
可能发生的情况是 mock_s3
函数中的 s3
对象出于性能原因正在缓存目录列表。您使用单独的实例创建新的空文件,因此外部实例不知道任何内容已更改。尝试在 add_file
和 s3.ls
之间插入 s3.invalidate_cache()
。
在 unittest
ing 的上下文中,我得到了以下 setUp
和 teadDown
:
def setUp(self):
self.mock_s3.start()
s3_conn = boto3.client('s3', 'us-west-2')
s3_conn.create_bucket(Bucket='bucket')
self.s3 = s3fs.S3FileSystem()
def tearDown(self):
self.mock_s3.stop()
并避免了装饰器的使用。这对问题中描述的案例没有直接帮助,但是,由于这个用例对我来说是个问题,所以我把它放在这里以供参考。