How to unit test and mock a method that takes a file as a parameter

Refresh

December 2018

Views

4.3k time

3

I have a class CollectionObject which creates a ArrayList.

public class CollectionObject {

    private List<String> collectionObject;

    public CollectionObject() {
        collectionObject = new ArrayList<String>();
    }

    public List<String> getCollectionObject() {
        return collectionObject;
    }

    public void add(final String stringToWrite) throws VerifyException {
        collectionObject.add(stringToWrite);
    }
}

There is another class which takes in the class CollectionObject and uses it to write the contents of the file to the class CollectionObject.

public class ReaderFileWriterObjectService {

    private BufferedReader bufferedReader;
    private CollectionObject collectionObject;
    private String line;

    public CollectionObject getCollectionObjectAfterWritingFromAFile(final File file)
            throws VerifyException, IOException {
        collectionObject = new CollectionObject();
        bufferedReader = new BufferedReader(new FileReader(file));
        while ((line = bufferedReader.readLine()) != null) {
            collectionObject.add(line);
        }
        bufferedReader.close();
        return collectionObject;
    }

How to Test and Mock the method of the class ReaderFileWriterObjectService?

6 answers

2

Я делаю то же самое, и следующая мысль работает, я надеюсь, что это будет работать для и тоже,

 @InjectMocks
 private CollectionObject collectionObject;

@Test
public void getCollectionObjectAfterWritingFromAFile() throws Exception {
    CollectionObject  expectedObject =new CollectionObject();
    List<String> expectedList=new ArrayList<String>();
    expectedList.add("100");

    CollectionObject  resultObject =new CollectionObject();

    BufferedReader reader=new BufferedReader(new StringReader("100"));
    PowerMockito.mock(BufferedReader.class);
    PowerMockito.mock(FileReader.class);
    PowerMockito.whenNew(FileReader.class).withArguments("test10.csv").thenReturn(null);
    PowerMockito.whenNew(BufferedReader.class).withArguments(null).thenReturn(reader);
    resultObject=collectionObject.getCollectionObjectAfterWritingFromAFile( "test10.csv");
    assertEquals(expectedObject ,resultObject );
}
1

Вы можете использовать JUnit в TemporaryFolder для создания файла и скопировать содержимое из ресурса к нему.

public YourText {
  @Rule
  public TemporaryFolder folder = new TemporaryFolder();

  @Test
  public void checkSomething() throws Exception {
    InputStream resource = getClass().getResourceAsStream("/your/resource");
    File file = folder.newFile();
    Files.copy(resource, file);
    ReaderFileWriterObjectService service = ...
    CollectionObject collection = service
        .getCollectionObjectAfterWritingFromAFile(file);
    ...
  }
0

Хорошо, сначала давайте рассмотрим, что делать и хотите проверить? Если это модульное тестирование, то и не хочу, чтобы проверить интеграцию, как связь с файловой системой, вы должны проверить свою собственную логику и ваша логика что-то вроде: 1) Читать следующую строку из файла, используя интеграцию файловой системы 2) добавить эту строку в мой объект

Второй шаг, который вы не должны проверить, так как этот метод слишком легко сломать. Первый шаг, который вы не можете проверить причиной он выполняет интеграции вызова. Так что я не думаю, что здесь и нужно модульное тестирование

Но если ваша логика будет более сложной, то вы можете ввести интерфейс обертку и издеваетесь его в тесте:

public interface FileWrapper{
  public String readLine();
  public void close();
}
public class FileWrapperImpl implements FileWrapper{
  private File file;
  private BufferedReader reader;

  public FileWrapperImpl (File file){
     this.file = file;
     this.reader= ...
  }

  public String readLine(){
    return reader.nextLine();
  }
}

И тогда ваш ReaderFileWriterObjectService:

 public CollectionObject getCollectionObjectAfterWritingFromAFile(FileWrapper wrapper)
        CollectionObject  collectionObject = new CollectionObject();
        while ((line = wrapper.readLine()) != null) {
            collectionObject.add(line);
        }
        wrapper.close();
        return collectionObject;
    }

И теперь вы можете легко издеваться FileWrapper для испытания и передать его в службу

4

Позвольте мне дополнить на @ ответ LouisWasserman в .

Вы просто не можете протестировать API - интерфейсы , которые полагаются на java.io.File; Этот класс не может быть надежно протестированы (даже если это даже не finalна уровне JDK).

Но это не случай с новой файловой системой API, которая появилась с Java 7.

Также известно как JSR 203, этот API предоставляет единый API для любого носителя обеспечивает «объекты» файловой системы.

Короткий рассказ:

  • «файловая система объект» материализуются на пути в этом API;
  • любая JDK реализации JSR 203 (т.е. любая Java 7+ версия) поддерживает этот API;
  • получить путь от ресурса по умолчанию FileSystem , вы можете использовать Paths.get();
  • но не ограничиваются этим.

Короче говоря, в вашем API и теста, вы должны использовать Path, не File. И если вы хотите , чтобы проверить , что связано с некоторой файловой системы ресурса, используйте JDK в Filesкласс для тестирования Pathэкземпляров.

И вы можете создать FileSystemS из основной, на основе диска, файловой системы. Рекомендация: используйте это .

fge
0

Ты не можешь. Вы в значительной степени не повезло. Лучше дизайн будет принимать Java 7 java.nio.file.FileSystemи Pathчто может быть выгружено для реализации теста, например https://github.com/google/jimfs .

0

Я хотел бы предложить изменения API, чтобы принять чтение или BufferedReader - те могут быть издевались. Скрыть зависимость от файла с заводом.