Filsystem Mocking med Jimfs

1. Oversigt

Når vi tester komponenter, der bruger I / O-operationer tungt, kan vores test typisk lide af flere problemer såsom dårlig ydeevne, platformafhængighed og uventet tilstand.

I denne vejledning vi tager et kig på, hvordan vi kan afhjælpe disse problemer ved hjælp af in-memory-filsystemet Jimfs.

2. Introduktion til Jimfs

Jimfs er et in-memory filsystem, der implementerer Java NIO API og understøtter næsten alle funktioner i det. Dette er især nyttigt, da det betyder, at vi kan efterligne et virtuelt in-memory-filsystem og interagere med det ved hjælp af vores eksisterende java.nio lag.

Som vi skal se, kan det være en fordel at bruge et spottet filsystem i stedet for et rigtigt for at:

  • Undgå at være afhængig af det filsystem, der i øjeblikket kører testen
  • Sørg for, at filsystemet samles med den forventede tilstand ved hver testkørsel
  • Hjælp med at fremskynde vores tests

Da filsystemer varierer betydeligt, er det også let at teste med filsystemer fra forskellige operativsystemer ved hjælp af Jimfs.

3. Maven-afhængigheder

Lad os først og fremmest tilføje de projektafhængigheder, vi har brug for til vores eksempler:

 com.google.jimfs jimfs 1.1 

Jimfs afhængighed indeholder alt, hvad vi har brug for for at kunne bruge vores spottede filsystem. Derudover skriver vi tests ved hjælp af JUnit5.

4. En simpel filopbevaring

Vi starter med at definere en simpel FileRepository klasse, der implementerer nogle standard CRUD-operationer:

offentlig klasse FileRepository {void create (Sti sti, String filnavn) {Sti filePath = sti.resolve (filnavn); prøv {Files.createFile (filePath); } fange (IOException ex) {smid ny UncheckedIOException (ex); }} Strenglæsning (sti) {prøv {returner ny streng (Files.readAllBytes (sti)); } fange (IOException ex) {smid ny UncheckedIOException (ex); }} Opdatering af streng (sti, streg newContent) {prøv {Files.write (sti, newContent.getBytes ()); returnere newContent; } fange (IOException ex) {kast ny UncheckedIOException (ex); }} ugyldig sletning (sti) {prøv {Files.deleteIfExists (sti); } fange (IOException ex) {smid ny UncheckedIOException (ex); }}}

Som vi kan se, bruger hver metode standard java.nio klasser.

4.1. Oprettelse af en fil

I dette afsnit skriver vi en test, der tester skab metode fra vores arkiv:

@Test @DisplayName ("Skal oprette en fil i et filsystem") ugyldigt givenUnixSystem_whenCreatingFile_thenCreatedInPath () {FileSystem fileSystem = Jimfs.newFileSystem (Configuration.unix ()); String fileName = "newFile.txt"; Sti pathToStore = fileSystem.getPath (""); fileRepository.create (pathToStore, filnavn); assertTrue (Files.exists (pathToStore.resolve (filnavn))); }

I dette eksempel har vi brugt statisk metode Jimfs.newFileSystem () at oprette et nyt filsystem i hukommelsen. Vi sender et konfigurationsobjekt Configuration.unix (), hvilket skaber en uforanderlig konfiguration for et Unix-filsystem. Dette inkluderer vigtig OS-specifik information, såsom stiadskillere og information om symbolske links.

Nu hvor vi har oprettet en fil, kan vi kontrollere, om filen blev oprettet med succes på det Unix-baserede system.

4.2. Læsning af en fil

Dernæst tester vi metoden, der læser indholdet af filen:

@Test @DisplayName ("Skal læse indholdet af filen") ugyldigt givetOSXSystem_whenReadingFile_thenContentIsReturned () kaster undtagelse {FileSystem fileSystem = Jimfs.newFileSystem (Configuration.osX ()); Sti resourceFilePath = fileSystem.getPath (RESOURCE_FILE_NAME); Files.copy (getResourceFilePath (), resourceFilePath); Strengindhold = fileRepository.read (resourceFilePath); assertEquals (FILE_CONTENT, indhold); }

Denne gang har vi kontrolleret, om det er muligt at læse indholdet af filen på en macOS (tidligere OSX) -system ved blot at bruge en anden type konfiguration - Jimfs.newFileSystem (Configuration.osX ()).

4.3. Opdatering af en fil

Vi kan også bruge Jimfs til at teste metoden, der opdaterer indholdet af filen:

@Test @DisplayName ("Skal opdatere indholdet af filen") ugyldigt givenWindowsSystem_whenUpdatingFile_thenContentHasChanged () kaster undtagelse {FileSystem fileSystem = Jimfs.newFileSystem (Configuration.windows ()); Sti resourceFilePath = fileSystem.getPath (RESOURCE_FILE_NAME); Files.copy (getResourceFilePath (), resourceFilePath); String newContent = "Jeg opdaterer dig."; Strengindhold = fileRepository.update (resourceFilePath, newContent); assertEquals (nyt indhold, indhold); assertEquals (newContent, fileRepository.read (resourceFilePath)); }

Ligeledes har vi denne gang kontrolleret, hvordan metoden opfører sig på en Windows-baseret system ved hjælp af Jimfs.newFileSystem (Configuration.windows ()).

4.4. Sletning af en fil

For at afslutte test af vores CRUD-operationer, lad os teste metoden, der sletter filen:

@Test @DisplayName ("Skal slette fil") ugyldigt givenCurrentSystem_whenDeletingFile_thenFileHasBeenDeleted () kaster undtagelse {FileSystem fileSystem = Jimfs.newFileSystem (); Sti resourceFilePath = fileSystem.getPath (RESOURCE_FILE_NAME); Files.copy (getResourceFilePath (), resourceFilePath); fileRepository.delete (resourceFilePath); assertFalse (Files.exists (resourceFilePath)); }

I modsætning til tidligere eksempler har vi brugt Jimfs.newFileSystem () uden at angive en filsystemkonfiguration. I dette tilfælde opretter Jimfs et nyt filhukommelse i hukommelsen med en standardkonfiguration, der passer til det aktuelle operativsystem.

5. Flytning af en fil

I dette afsnit lærer vi, hvordan man tester en metode, der flytter en fil fra en mappe til en anden.

Lad os først implementere bevæge sig metode ved hjælp af standarden java.nio.file. fil klasse:

ugyldig flytning (sti oprindelse, sti destination) {prøv {Files.createDirectories (destination); Files.move (oprindelse, destination, StandardCopyOption.REPLACE_EXISTING); } fange (IOException ex) {smid ny UncheckedIOException (ex); }}

Vi skal bruge en parametreret test for at sikre, at denne metode fungerer på flere forskellige filsystemer:

privat statisk strøm giveFileSystem () {return Stream.of (Arguments.of (Jimfs.newFileSystem (Configuration.unix ())), Arguments.of (Jimfs.newFileSystem (Configuration.windows ())), Arguments.of (Jimfs. newFileSystem (Configuration.osX ()))); } @ParameterizedTest @DisplayName ("Skal flytte fil til en ny destination") @MethodSource ("giveFileSystem") ugyldigt givenEachSystem_whenMovingFile_thenMovedToNewPath (FileSystem fileSystem) kaster Undtagelse {Path origin = fileSystem.getPath (RESOURCE_FILE_NAME); Files.copy (getResourceFilePath (), oprindelse); Stedestination = fileSystem.getPath ("newDirectory", RESOURCE_FILE_NAME); fileManipulation.move (oprindelse, destination); assertFalse (Files.exists (oprindelse)); assertTrue (Files.exists (destination)); }

Som vi kan se, har vi også været i stand til at bruge Jimfs til at teste, at vi kan flytte filer på en række forskellige filsystemer fra en enkelt enhedstest.

6. Afhængige tests til operativsystem

Lad os oprette en for at demonstrere en anden fordel ved at bruge Jimfs FilePathReader klasse. Klassen er ansvarlig for at returnere den virkelige systemsti, som selvfølgelig er OS-afhængig:

klasse FilePathReader {String getSystemPath (Sti sti) {prøv {retur sti .toRealPath () .toString (); } fange (IOException ex) {kast ny UncheckedIOException (ex); }}}

Lad os nu tilføje en test til denne klasse:

klasse FilePathReaderUnitTest {privat statisk streng DIRECTORY_NAME = "baeldung"; private FilePathReader filePathReader = ny FilePathReader (); @Test @DisplayName ("Skal få sti på windows") ugyldigt givenWindowsSystem_shouldGetPath_thenReturnWindowsPath () kaster undtagelse {FileSystem fileSystem = Jimfs.newFileSystem (Configuration.windows ()); Sti sti = getPathToFile (fileSystem); String stringPath = filePathReader.getSystemPath (sti); assertEquals ("C: \ work \" + DIRECTORY_NAME, stringPath); } @Test @DisplayName ("Skal få sti på unix") ugyldigt givetUnixSystem_shouldGetPath_thenReturnUnixPath () kaster undtagelse {FileSystem fileSystem = Jimfs.newFileSystem (Configuration.unix ()); Sti sti = getPathToFile (fileSystem); String stringPath = filePathReader.getSystemPath (sti); assertEquals ("/ work /" + DIRECTORY_NAME, stringPath); } privat sti getPathToFile (FileSystem fileSystem) kaster undtagelse {Path path = fileSystem.getPath (DIRECTORY_NAME); Files.createDirectory (sti); returvej }}

Som vi kan se, adskiller output til Windows sig fra den fra Unix, som vi havde forventet. I øvrigt, vi behøvede ikke at køre disse tests ved hjælp af to forskellige filsystemer - Jimfs spottede det automatisk for os.

Det er værd at nævne det Jimfs støtter ikke tilFil () metode, der returnerer en java.io-fil. Det er den eneste metode fra Sti klasse, der ikke understøttes. Derfor kan det være bedre at betjene en InputStream snarere end en Fil.

7. Konklusion

I denne artikel har vi lært, hvordan man bruger Jim-filsystem i hukommelsen til at spotte filsysteminteraktioner fra vores enhedstest.

Først startede vi med at definere et simpelt arkiv med flere CRUD-operationer. Derefter så vi eksempler på, hvordan man testede hver af metoderne ved hjælp af en anden filsystemtype. Endelig så vi et eksempel på, hvordan vi kan bruge Jimfs til at teste OS-afhængig filsystemhåndtering.

Som altid er koden til disse eksempler tilgængelig på Github.


$config[zx-auto] not found$config[zx-overlay] not found