Модуль: Как написать тестовый пример с использованием jUnit и Mockito

Я очень новичок в Mockito, jUnit и TDD в целом, и я пытаюсь научиться правильно делать TDD. Мне нужна пара примеров, чтобы запустить мой мозг. ПОЖАЛУЙСТА, помогите мне

Итак, у меня есть метод getNameInc(String dirPath, String filenName). Таким образом, дается имя файла, например bankAccount.pdf, и если в этой папке нет файла с именем bankAccount.pdf, то возвращается bankAccountAA.pdf. Если существует один bankAccount.pdf, то return bankAccountBB.pdf increment это AA-ZZ. Когда он достигает ZZ, он возвращается к AA. Я уже реализую логику этого метода. Как выполнить модульное тестирование этого метода с помощью Mockiti и jUnit?

ИЗМЕНИТЬ

Вот класс и методы, которые задействованы.

public class PProcessor{

    private final Map<Integer, String> incMap = new HashMap<Integer, String>();

    private String getNameInc(String dirPath, String filenName){
         String[] nameList = new File(dirPath).list(new FilenameFilter(){
            public boolean accept(File file, String name) {
                //only load pdf files
                return (name.toLowerCase().endsWith(".pdf"));
            }
        });
        //Return the number of occurance that a given file name appear
        //inside the output folder.
        int freq = 0;
        for(int i=0; i<nameList.length; i++){

            if(fileName.equals(nameList[i].substring(0, 8))){
                freq++;
            }
        }
        return incMap.get(freq);
    }

    private void generateIncHashMap(){
        incMap.put(new Integer(0), "AA");
        incMap.put(new Integer(1), "BB");
        incMap.put(new Integer(2), "CC");
        ...
    }
}

generateIncHashMap() будет вызываться в конструкторе для предварительной генерации хеш-карты


person Thang Pham    schedule 17.05.2011    source источник
comment
Я думаю, вы упускаете смысл издевательства. Макет не должен реализовывать какую-либо логику. Как правило, он просто возвращает жестко закодированные значения на основе тестового примера, в котором он используется.   -  person Mike Deck    schedule 18.05.2011
comment
@Mike: я уже реализую логику. Метод getNameInc(String dirPath, String fileName) мною уже реализован. Мне просто интересно, как провести модульное тестирование. Это может быть мокито или старый добрый jUnit. Я пытаюсь усвоить идею.   -  person Thang Pham    schedule 18.05.2011
comment
рад, что вы хотите использовать TDD! Но из вашего последнего комментария звучит так, будто вы сначала написали логику... а это противоположно тому, как работает TDD. Сначала напишите тест, который не проходит, затем сделайте так, чтобы тест прошел с реальным кодом, затем рефакторинг этого кода, чтобы он был чище, но не делал ничего, кроме прохождения теста. Затем напишите еще один неудачный тест. Mockito поможет вам создать сложные сервисы, от которых зависит ваш класс. Можете ли вы обновить свой вопрос с классами, которые сотрудничают с этой функцией?   -  person alpian    schedule 18.05.2011
comment
@alpian: я обновляю свой пост некоторыми кодами. Можете ли вы взглянуть на них.   -  person Thang Pham    schedule 18.05.2011


Ответы (2)


Я предполагаю, что вы пытаетесь проверить свой метод getNameInc(..). Когда вы вызываете его, он ищет файлы в указанном вами каталоге и на основе того, что он находит, украшает имя, которое вы ему дали.

Чтобы сделать класс пригодным для модульного тестирования, вы должны абстрагировать зависимость от файловой системы, чтобы в макете вы могли имитировать любое содержимое каталога, которое хотите. Ваш класс примет экземпляр этого интерфейса в качестве зависимости и вызовет его, чтобы узнать, что находится в каталоге. Когда вы используете класс в своей программе по-настоящему, вы предоставляете реализацию этого интерфейса, которая делегирует вызовы файловой системы JDK. Когда вы выполняете модульное тестирование класса, вы предоставляете Mockito макеты этого интерфейса.

Не добавляйте слишком много логики в класс FilesystemImpl, поскольку для него нельзя написать строгий модульный тест. Держите его в виде очень простой оболочки вокруг файловой системы, чтобы все интеллектуальные функции находились в классе Yourclass, для которого вы напишете множество модульных тестов.

public interface Filesystem {
    boolean contains(String dirpath, String filename);
}

public class FilesystemImpl {
    boolean contains(String dirpath, String filename) {
        // Make JDK calls to determine if the specified directory has the file.
        return ...
    }
}

public class Yourmainclass {
    public static void main(String[] args) {

         Filesystem f = new FilesystemImpl();
         Yourclass worker = new Yourclass(f);
         // do something with your worker
         // etc...
    }
}

public class Yourclass {
    private Filesystem filesystem;

    public Yourclass(Filesystem filesystem) {
        this.filesystem = filesystem;
    }

    String getNameInc(String dirpath, String filename) {
       ...
       if (filesystem.contains(dirpath, filename) {
          ...
       }
    }

}

public class YourclassTest {

   @Test
   public void testShouldAppendAAWhenFileExists() {
       Filesystem filesystem = Mockito.mock(Filesystem.class);
       when(filesystem.contains("/some/mock/path", "bankAccount.pdf").thenReturn(true);
       Yourclass worker = new Yourclass(filesystem);
       String actual = worker.getNameInc("/some/mock/path", "bankAccount.pdf");
       assertEquals("bankAccountAA.pdf", actual);
   }

   @Test
   public void testShouldNotAppendWhenFileDoesNotExist {
       Filesystem filesystem = Mockito.mock(Filesystem.class);
       when(filesystem.contains("/some/mock/path", "bankAccount.pdf").thenReturn(false);
       Yourclass worker = new Yourclass(filesystem);
       String actual = worker.getNameInc("/some/mock/path", "bankAccount.pdf");
       assertequals("bankAccount.pdf", actual);
   }
}

Поскольку между тестами много дублирования, вы, вероятно, создадите метод установки и выполните там часть работы, а также создадите некоторые переменные экземпляра для использования в тестах:

    private static final String TEST_PATH = "/some/mock/path";
    private static final String TEST_FILENAME = "bankAccount.pdf";
    private Filesystem filesystem;
    private Yourclass worker;

    @Before
    public void setUp() {
        filesystem = Mockito.mock(Filesystem.class);
        worker = new Yourclass(filesystem);
    }

    @Test
   public void testShouldAppendAAWhenFileExists() {
       when(filesystem.contains(TEST_PATH, TEST_FILENAME).thenReturn(true);
       String actual = worker.getNameInc(TEST_PATH, TEST_FILENAME);
       assertEquals("bankAccountAA.pdf", actual);
   }

   etc...
person Ladlestein    schedule 17.05.2011
comment
не должен ли FilesystemImpl класс, который реализует Filesystem, а не interface? - person Thang Pham; 18.05.2011

Для того, что вы там описали, я бы не стал возиться с Mockito, похоже, не над чем издеваться (потому что с файловой системой легко манипулировать).

Я бы проверил... - Что произойдет, если я вызову getNameInc, а соответствующих файлов уже нет - Что произойдет, если я вызову getNameInc, а там уже есть файлы AA-YY - Что произойдет, если я вызову getNameInc, а файл ZZ уже есть

Однако смысл TDD в том, что вы должны были уже написать эти тесты, а затем реализовать свой код, чтобы тесты прошли. Таким образом, вы действительно не будете использовать TDD, поскольку у вас уже есть код.

person sMoZely    schedule 17.05.2011
comment
Да, я знаю, что внедрять тест после кода не имеет особого смысла, но так как это для меня ново. Я пытаюсь овладеть TDD - person Thang Pham; 18.05.2011