1- from unittest .mock import AsyncMock , patch
1+ import tempfile
2+ from pathlib import Path
3+ from unittest .mock import AsyncMock , patch , MagicMock
4+
5+ import pytest
26
37from app .services import destination_service
48from shared .enums import StorageType
59from shared .models import Destination
610from shared .schemas import DestinationCreate
711
8- # All tests patch Path.is_dir so fake paths like /tmp/test pass validation,
9- # and _get_available_bytes so disk checks don't run on test fixtures.
10- _PATCHES = [
11- patch (
12+ # Shared patches: BACKUP_ROOT=/tmp so test paths like /tmp/test pass,
13+ # mkdir is no-op, disk check returns None.
14+ _patches = {
15+ "root" : patch ("app.services.destination_service.BACKUP_ROOT" , Path (tempfile .gettempdir ())),
16+ "mkdir" : patch ("app.services.destination_service.Path.mkdir" , MagicMock ()),
17+ "avail" : patch (
1218 "app.services.destination_service._get_available_bytes" ,
1319 new_callable = AsyncMock ,
1420 return_value = None ,
1521 ),
16- patch ("app.services.destination_service.Path.is_dir" , return_value = True ),
17- ]
22+ }
23+
24+
25+ def _apply_patches ():
26+ mocks = {k : p .start () for k , p in _patches .items ()}
27+ return mocks
28+
29+
30+ def _stop_patches ():
31+ for p in _patches .values ():
32+ p .stop ()
1833
1934
20- def _apply (fn ):
21- for p in reversed (_PATCHES ):
22- fn = p (fn )
23- return fn
35+ @pytest .fixture (autouse = True )
36+ def _patch_destination_service ():
37+ _apply_patches ()
38+ yield
39+ _stop_patches ()
2440
2541
26- @_apply
27- async def test_create_destination (mock_is_dir , mock_avail , db_session , admin_user ):
28- body = DestinationCreate (alias = "Test Dest" , path = "/tmp/test" )
42+ async def test_create_destination (db_session , admin_user ):
43+ body = DestinationCreate (alias = "Test Dest" , path = f"{ tempfile .gettempdir ()} /test" )
2944 result = await destination_service .create_destination (db_session , admin_user , body )
3045 assert result .alias == "Test Dest"
3146 assert result .storage_type == StorageType .LOCAL
3247 assert result .is_default is False
3348
3449
35- @_apply
36- async def test_create_default_clears_old_default (mock_is_dir , mock_avail , db_session , admin_user ):
37- body1 = DestinationCreate (
38- alias = "First" , path = "/tmp/first" , is_default = True
39- )
50+ async def test_create_default_clears_old_default (db_session , admin_user ):
51+ body1 = DestinationCreate (alias = "First" , path = f"{ tempfile .gettempdir ()} /first" , is_default = True )
4052 first = await destination_service .create_destination (db_session , admin_user , body1 )
4153 assert first .is_default is True
4254
43- body2 = DestinationCreate (
44- alias = "Second" , path = "/tmp/second" , is_default = True
45- )
55+ body2 = DestinationCreate (alias = "Second" , path = f"{ tempfile .gettempdir ()} /second" , is_default = True )
4656 second = await destination_service .create_destination (db_session , admin_user , body2 )
4757 assert second .is_default is True
4858
@@ -51,9 +61,8 @@ async def test_create_default_clears_old_default(mock_is_dir, mock_avail, db_ses
5161 assert refreshed_first .is_default is False
5262
5363
54- @_apply
55- async def test_list_destinations (mock_is_dir , mock_avail , db_session , admin_user ):
56- body = DestinationCreate (alias = "Listed" , path = "/tmp/listed" )
64+ async def test_list_destinations (db_session , admin_user ):
65+ body = DestinationCreate (alias = "Listed" , path = f"{ tempfile .gettempdir ()} /listed" )
5766 await destination_service .create_destination (db_session , admin_user , body )
5867
5968 results = await destination_service .list_destinations (db_session )
@@ -62,12 +71,9 @@ async def test_list_destinations(mock_is_dir, mock_avail, db_session, admin_user
6271 assert "Listed" in aliases
6372
6473
65- @_apply
66- async def test_delete_destination (mock_is_dir , mock_avail , db_session , admin_user ):
67- body = DestinationCreate (alias = "ToDelete" , path = "/tmp/delete" )
68- created = await destination_service .create_destination (
69- db_session , admin_user , body
70- )
74+ async def test_delete_destination (db_session , admin_user ):
75+ body = DestinationCreate (alias = "ToDelete" , path = f"{ tempfile .gettempdir ()} /delete" )
76+ created = await destination_service .create_destination (db_session , admin_user , body )
7177
7278 await destination_service .delete_destination (db_session , str (created .id ))
7379
0 commit comments