Статьи

Файлы-макеты для тестирования JUnit веб-приложения Spring Boot на Synology NAS

Для приложения Spring Boot, которое будет проверять файлы резервных копий на NAS-устройстве Synology RS815 +, мы хотели иметь возможность легко протестировать файлы, хранящиеся на этом NAS, без необходимости копировать 7 ТБ, хранящиеся на нем.

В идеале мы хотели создать такую ​​же файловую структуру для использования веб-приложения в профиле разработки Spring, а также использовать эти файловые структуры в тесте JUnit.

Представляем FileStructureCreator

Мы начали с создания нового класса FileStructureCreator который выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@Getter
@Setter
public class FileStructureCreator implements Closeable {
 
  public static final Path baseTestPath = Paths.get("testFiles");
  private Path fileStructureBasePath;
 
  public static FileStructureCreator create(Path file) {
      return createStructure(file, false);
  }
 
  public static FileStructureCreator createTempDirectory(Path file) {
      return createStructure(file, true);
  }
 
  @SneakyThrows
  private static FileStructureCreator createStructure(Path file, boolean createTempDirectory) {
      FileStructureCreator fileStructureCreator = new FileStructureCreator();
 
      if (!Files.exists(baseTestPath)) {
          Files.createDirectory(baseTestPath);
      }
 
      String path = baseTestPath.toString() + (createTempDirectory ? "/" + UUID.randomUUID().toString() : "")
              + "/";
      Path basePath = Paths.get(path);
      fileStructureCreator.setFileStructureBasePath(basePath);
      FileUtils.forceMkdir(basePath.toFile());
 
      try (Stream<String> stream = Files.lines(file)) {
          stream.forEach(line -> {
              Metadata fileMetaData = Metadata.from(line);
 
              Path fileEntry = Paths.get(path + fileMetaData.getWindowsSafeFilename());
              try {
                  FileUtils.forceMkdir(fileEntry.getParent().toFile());
                  if (!Files.exists(fileEntry)) {
                      Files.write(fileEntry, line.getBytes());
                      Files.setLastModifiedTime(fileEntry, FileTime.from(fileMetaData.getModificationTime()));
                  }
              } catch (IOException ignore) {
                  throw new RuntimeException("Exception creating directory: " + fileEntry.getParent());
              }
          });
      }
      return fileStructureCreator;
  }
  @Override
  @SneakyThrows
  public void close() {
      if (fileStructureBasePath != null) {
          FileUtils.deleteDirectory(fileStructureBasePath.toFile());
      }
  }
}

Это в основном создает всю структуру каталогов и необходимые файлы. Нам просто нужно передать ему базовый файл, который содержит метаданные файловой структуры.

Метаданные содержат метку времени, размер файла и путь к этому файлу. Это выглядит так:

1
2
3
4
5
6
7
2016-04-05T10:30:15.012345678   5120
 
backupftp/@eaDir/sharesnap_share_configuration/SYNO@.quota
 
2018-02-26T00:00:09.012345678  169
 
backupftp/@eaDir/sharesnap_share_configuration/share_configuration

На нашем Synology NAS мы можем легко сгенерировать файл со всей древовидной структурой (определенной) директории, выполнив эту команду:

1
2
find backupftp -type f -printf
"%TY-%Tm-%TdT%TH:%TM:%.12TS\t%s\t%p\n">test/backupftp.files.txt

Скопируйте созданный файл с вашего Synology NAS в ваш проект.

В тесте JUnit мы используем класс FileStructureCreator как в примере ниже. Обратите внимание, что FileStructureCreator реализует AutoCloseable , поэтому мы можем использовать блок try / catch для очистки файлов после завершения теста.

01
02
03
04
05
06
07
08
09
10
11
@Value("classpath:/TestDiskConsistencyPolicy-notEnoughFileSets.txt")
private Path notEnoughFileSets;
 
@Test(expected = RuntimeException.class)
public void backupSetWithNoFileSetsThrowException() {
  try( FileStructureCreator creator = FileStructureCreator.createTempDirectory(notEnoughFileSets) ) {
      BackupSet backupSet = BackupSet.builder().uri(creator.getFileStructureBasePath().toString()).build();
      new DiskConsistencyPolicy(backupSet).execute();
      assertTrue( "Expecting a RuntimeException here", false);
  }
}

Для приложения Spring Boot мы просто определяем класс @Configuration который будет создавать структуры данных для наших @Configuration файловых ресурсов, как определено на Synology NAS.

01
02
03
04
05
06
07
08
09
10
11
12
@Configuration
@Profile("dev")
public class TestFilesInstaller {
  @Bean
  public FileStructureCreator ftpFiles(@Value("classpath:/backupftp.files.txt") Path file) {
      return FileStructureCreator.create(file);
  }
  @Bean
  public FileStructureCreator nfsFiles(@Value("classpath:/backupnfs.files.txt") Path file) {
      return FileStructureCreator.create(file);
  }
}

Поскольку они определены как @Bean , метод close() будет автоматически вызываться при close() приложения, удаляя все файлы с диска при остановке приложения Spring Boot.
Просто … не запускайте профиль разработчика в производство; Я дам вам понять, что происходит. 😉
В будущем мы покажем вам, как создать средство проверки резервных копий для мониторинга и проверки резервных копий на вашем NAS.

См. Оригинальную статью здесь: Файлы-макеты для тестирования JUnit веб-приложения Spring Boot на Synology NAS

Мнения, высказанные участниками Java Code Geeks, являются их собственными.