Чи існують фреймворки підробленої файлової системи для Java? [зачинено]


83

Я представляю тести в проекті, який активно використовує операції введення-виведення (у цьому випадку файлова система). Система постійно відкриває / закриває файли, перевіряє наявність файлів, видаляє їх тощо.

Незабаром стало очевидним, що регулярне знущання не принесе великої користі, оскільки це ускладнить мої тести та налаштування аргументів. З іншого боку, наявність підробленої файлової системи було б неймовірним, і, на мою думку, досить легко налаштувати.

Здається, рубінові хлопці зробили це знову, і саме про це я прошу в ruby: http://ozmm.org/posts/fakefs.html .

Чи існує щось подібне для Java?


1
Схоже, на рівні програми це простіше зробити на мовах без системи статичного типу. У Java файл File / FileInputStream / FileOutputStream завжди буде посилатися на файлову систему базової системи - якщо ви не виправите віртуальну машину.
Paŭlo Ebermann

Існують такі інтерфейси, як JavaFileManager або FileSystemView, які ви можете реалізувати, але більшість програм не використовують їх.
Paŭlo Ebermann

@ 1-й коментар: Я це добре знаю. На даний момент я замінив усі способи використання файлу на власне ім’я файлу, яке містить лише ім’я файлу як рядок. Вся логіка введення-виведення була зосереджена на інтерфейсі IFileSystem. Проблема, яка виникає у мене, полягає в тому, що впровадження фальшивої файлової системи так, як мені було потрібно, було б як цілий день роботи (з підтримкою файлів + папок + прихованих файлів + перейменувань + отримання лише шляху від імені файлу + ...) та тестуючи його, щоб знати, чи насправді це правильно.
пожирав елізій

1
Оскільки ви згадали Ruby в OP, я хотів би лише додати тут, що в C # також є еквівалент, System.IO.Abstractions, який я почав використовувати нещодавно, і це цілком добре.
julealgon

Відповіді:


52

Google має реалізовану в пам’яті реалізацію Java 7 FileSystemProvider. Проект називається jimfs .


Якщо ви використовуєте Java 6 або старішу версію, є альтернатива: я раніше користувався Apache Commons VFS із великим успіхом. Здається, це схоже на користувальницький FileSystemProvider, про якого згаданий інший відповідач, є в Java 7.

Він поставляється з попередньо завантаженими декількома реалізаціями файлової системи: File, RAM, S / FTP та Jar, щоб назвати декілька. Я також бачив плагін для S3 .


6
+1 до jimfs, що дозволило мені протестувати свій код без жодної зміни. (Я використовував Pathвипадково)
user1071136

35

У Java 6 та попередніх версіях це важко, оскільки класи подобаються Fileі FileInputStreamне забезпечують можливості відправлення до різних "віртуальних файлових систем" у просторі Java.

У Java 7 є підтримка віртуальних файлових систем; див. Розробка користувацького постачальника файлової системи . Не знаю, чи це дозволить вам робити те, що ви хочете зробити, але це гарне місце, щоб почати шукати.


Ме Враховуючи той факт, що, схоже, насправді не існує жодної підробленої файлової системи, я гадаю, що я просто впроваджу мінімальну реалізацію самостійно. Я нічого не виграю, використовуючи FileSystemProvider

Насправді, ви виграєте за допомогою FileSystemProvider:

  • Ви впроваджуєте те, що (якщо воно буде випущено за ліцензією з відкритим кодом), може бути дуже корисним для інших людей на вашій посаді та для інших цілей.

  • Ви полегшуєте собі, якщо вирішите перейти на FileSystemProvider, над яким зараз може працювати хтось інший.


Цікаво, але, як видається, мені все одно доведеться впроваджувати файлову систему самостійно, не настільки корисно ;-(
пожирає elysium

6
Принаймні це дозволяє вам це робити. І як ви самі сказали - "це було б легко налаштувати" .
Stephen C

Ме Враховуючи той факт, що, схоже, насправді не існує жодної підробленої файлової системи, я гадаю, що я просто впроваджу мінімальну реалізацію самостійно. Я нічого не виграю, використовуючи FileSystemProvider.
пожирав елізій

@devoured elysium - див. моє оновлення.
Stephen C

2
+1 за рекомендацію написання та відкриття рішення
WickyNilliams,

19

Ви можете використовувати org.junit.rules.TemporaryFolderз пакета JUnit :

Правило TemporaryFolder дозволяє створювати файли та папки, які гарантовано будуть видалені після закінчення тестового методу (незалежно від того, проходить він чи не працює):

Приклад:

final TemporaryFolder testFolder = new TemporaryFolder();
testFolder.create();
final Path filePath = testFolder.newFile("input.txt").toPath();
final Path dirPath = testFolder.newFolder("subfolder").toPath();

Або залиште .toPath()частину:

final File filePath = testFolder.newFile("input.txt");

TemporaryFolder відсутня в пам'яті.
progonkpa

8

Ви можете абстрагувати використання File, використовуючи намір "десь писати дані", змінивши свій API на використання OutputStreamзамість a File, потім передавши API a FileOutputStreamу ваш робочий код, але передавши його a ByteArrayOutputStreamз ваших тестів. A ByteArrayOutputStream- це потік в пам'яті, тому він дуже швидкий, і ви можете просто перевірити його вміст, використовуючи його методи - він ідеально підходить для тестування. Є також відповідне, ByteArrayInputStreamякщо ви хочете прочитати дані.

Файлові системи, як правило, досить швидкі - якщо ви не робите багато файлових операцій вводу-виводу у своїх тестах, я б не турбувався.

Зверніть увагу, що створення Fileоб'єкта Java не створює файл на диску, тобто наступний код не спричиняє жодних змін на диску:

File f = new File("somepath"); // doesn't create a file on disk

new File ("щось") не створює файл на диску, але якщо ви спробуєте запустити майже будь-який з його методів, він буде використовувати файлову систему. Спробуйте новий файл ("xyz"). GetAbsolutePath (), щоб зрозуміти, що я маю на увазі ..
пожираний elysium

1
Я думаю, що люди припускають, що моє головне занепокоєння - швидкість. Це не так.
пожирав елізіум

1
Я вважаю, що завжди є гарною практикою абстрагувати будь-які ресурси, такі як файлові системи (так само, як ви пишете рівень доступу до даних до БД). це зазвичай досягається написанням інтерфейсу та тонкої обгортки навколо класу найнижчого рівня. якщо ви використовуєте ін'єкцію залежностей на найвищому рівні вашої програми, ви можете дуже легко розповсюдити макетну файлову систему (зауважте, що вона не повинна використовувати макетну структуру, просто "фіктивну" реалізацію інтерфейсу) через вашу програму.
WickyNilliams,

@devouredelysium new File("xyz").getAbsolutePath()абсолютно нічого не робить, окрім повернення шляху, який мав би файл , якби він існував. Це не змінює файлову систему; якщо файл не існує, він все одно повертає рядок шляху і не створює файл. Що ви мали на увазі під "побачити, що станеться"?
Чеська

1
Fileне є остаточним у моєму OpenJDK 7.
Дмитро Лазерка

6

Jimfs від Google - це файлова система NIO в пам'яті, яка чудово підходить для тестів.


4

Простим способом було б використання способу вашої системи для забезпечення файлової системи, повністю заснованої на оперативній пам'яті - tempfs в Linux, диску RAM в Windows.


Я не розумію, як це було б краще, ніж використання справжньої файлової системи (крім швидкості).
пожирав елізіум

Так, швидкість (і знос диска) була б основною причиною. Вибачте, можливо, я неправильно зрозумів вашу мету.
Paŭlo Ebermann

1
Моя мета - полегшити моє тестування. В даний час я не стурбований роботою.
пожирав елізіум

4

Здається, MockFTPServer має кілька реалізацій підробленої файлової системи (Unix / Windows)

Схоже, ви можете використовувати ці фальшиві реалізації файлової системи окремо від будь-яких концепцій FTP. Зараз я пробую це саме для тих самих цілей, які ви зазначили.


Я використовую UnixFakeFileSystem. Дуже добре працює як фальшива реалізація для моєї абстракції FileSystem.
Deano

2

Я не впевнений у конкретних фреймворках, але загальним підходом з точки зору ООП є написання абстрактних шарів поверх будь-якого коду доступу до файлів (інтерфейсів в достатку!) і, можливо, фасаду, щоб полегшити використання загальних операцій. тоді ви просто глузуєте над одним шаром під кодом, який ви зараз тестуєте, і це, по суті, фальшива файлова система (або, принаймні, код, який ви тестуєте, не знатиме інакше).

якщо ви задумаєтеся використовувати фреймворк інжекції залежностей для обробки цього, це полегшить можливість вимкнення компонентів для підробленої реалізації інтерфейсу. якщо ви будете слідувати шаблонам інверсії управління, передаючи будь-які залежності в конструктор класу, який ви тестуєте, це також полегшить тестування.

public interface IFileSystem {
   IFileHandle Load(string path);
   //etc
}

public class ClassBeingTested {
   public ClassBeingTested(IFileSystem fileSystem) {
      //assign to private field
   }

   public void DoSomethingWithFileSystem() {
       //utilise interface to file system here
       //which you could easily mock for testing purposes
       //by passing a fake implementation to the constructor
   }
}

Я сподіваюся, що мій java правильний, я давно не писав java, але, сподіваюся, ви отримаєте дрейф. сподіваюся, я не недооцінюю проблему тут і надмірно спрощую!

Звичайно, все це припускає, що ви маєте на увазі справжнє модульне тестування, тобто тестування найменших можливих одиниць коду, а не всієї системи. для інтеграційного тестування необхідний інший підхід.


1
Фальшива файлова система повинна мати власну логіку - це файлова система, як і будь-яка інша, але вона існує лише в пам'яті. Я хотів би уникнути необхідності програмувати собі таку файлову систему.
пожирав елізіум

який тип операцій з файловою системою ви хочете імітувати? блокування файлів? читання / письмо? або такі прості речі, як відкриття файлів, перевірка існування каталогів, створення файлів?
WickyNilliams

В основному прості операції, що стосуються перевірки, чи є файли файлами чи каталогами, якщо вони існують, для створення файлів та видалення файлів. Це, звичайно, при підтримці декількох папок та таких операцій, як "отримати шлях від цього імені файлу", "отримати відносний шлях від абсолютного шляху" тощо
пожираний elysium

Я думаю, як я вже заявив, створюючи звучання навколо фізичної файлової системи і завжди використовуючи це (завжди кодуючи інтерфейс) у всій програмі. тоді просто використовуйте ін’єкцію залежності, щоб продовжувати тестування. я знаю, що це монотонна робота, але як програмісти ми маємо робити ці речі, щоб отримати
чітке

Ви справді не отримуєте того, про що просять тут. Якщо я шукаю фальшиву файлову систему, це, мабуть, тому, що я вже зробив абстракцію всієї файлової системи у своєму додатку (як зазначено в коментарі OP). Мені просто потрібна фальшива реалізація файлової системи для використання в моїх тестах ...
пожирала елізіум

2

ShrinkWrap з проекту Arquillian, схоже, включає NI- сумісний у FileSystem пам'яті

Ви можете створити просту в пам'яті файлову систему, виконавши наступне:

FileSystem fs = ShrinkWrapFileSystems.newFileSystem(ShrinkWrap.create(GenericArchive.class))

Чи підтримує він файл: // протокол, не можу знайти документацію ....
Марко Васаполло


0

Я погуглив "Підроблену файлову систему Java" і знайшов це питання. На жаль, це все, що я знайшов. Тож я сам написав цю фальшиву FileSystem: https://github.com/dernasherbrezon/mockfs

Я використовую його для імітації винятків IOE під час читання / запису у файли. IOException може статися, наприклад, через "відсутність місця на диску", що майже неможливо змоделювати іншими способами.


-1

Він трохи старий, і це рішення здається лише для Linux, але виглядає непогано https://www.google.co.il/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=tmpfs%20on% 20ubuntu

tmpfs - це вкладений у пам'ять каталог (дані зникають при перезавантаженні). Після встановлення дані можна копіювати в них і працювати з ними з пам'яті.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.