Автор оригинала: mkyong.
Проще говоря, издевательство – это создание объектов, имитирующих поведение реальных объектов. Обратитесь к следующему тематическому исследованию:
Проверенный:
- Java 1.8
- Юнит 4.12
- Mockito 2.0.73-бета-версия
1. Примеры Java
Простой пример автора и книги.
1.1 Книжный сервис
для возврата списка книг по имени автора.
package com.mkyong.examples.mock; import java.util.List; public interface BookService { ListfindBookByAuthor(String author); }
package com.mkyong.examples.mock; import java.util.List; public class BookServiceImpl implements BookService { private BookDao bookDao; public BookDao getBookDao() { return bookDao; } public void setBookDao(BookDao bookDao) { this.bookDao = bookDao; } @Override public ListfindBookByAuthor(String name) { return bookDao.findBookByAuthor(name); } }
package com.mkyong.examples.mock; import java.util.List; public interface BookDao { ListfindBookByAuthor(String author); }
package com.mkyong.examples.mock; import java.util.List; public class BookDaoImpl implements BookDao { @Override public ListfindBookByAuthor(String name) { // init database // Connect to DB for data // return data } }
1.2 Валидатор книг.
package com.mkyong.examples.mock; public interface BookValidatorService { boolean isValid(Book book); }
package com.mkyong.examples.mock; public class FakeBookValidatorService implements BookValidatorService { @Override public boolean isValid(Book book) { if (book == null) return false; if ("bot".equals(book.getName())) { return false; } else { return true; } } }
1.3 Рассматривает Авторский Сервис Импл
, , он зависит от
Книжной службы (зависит от
BookDAO ) и
Службы проверки книг
package com.mkyong.examples.mock; public interface AuthorService { int getTotalBooks(String author); }
package com.mkyong.examples.mock; import java.util.List; import java.util.stream.Collectors; public class AuthorServiceImpl implements AuthorService { private BookService bookService; private BookValidatorService bookValidatorService; public BookValidatorService getBookValidatorService() { return bookValidatorService; } public void setBookValidatorService(BookValidatorService bookValidatorService) { this.bookValidatorService = bookValidatorService; } public BookService getBookService() { return bookService; } public void setBookService(BookService bookService) { this.bookService = bookService; } //How to test this method ??? @Override public int getTotalBooks(String author) { Listbooks = bookService.findBookByAuthor(author); //filters some bot writers List filtered = books.stream().filter( x -> bookValidatorService.isValid(x)) .collect(Collectors.toList()); //other business logic return filtered.size(); } }
2. Модульный тест
Создайте модульный тест для Авторской службы. получите общее количество книг()
2.1 Служба Author Impl
имеет две зависимости, вам необходимо убедиться, что обе настроены правильно.
package com.mkyong.mock; import com.mkyong.examples.mock.AuthorServiceImpl; import com.mkyong.examples.mock.BookDaoImpl; import com.mkyong.examples.mock.BookServiceImpl; import com.mkyong.examples.mock.FakeBookValidatorService; import org.junit.Test; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; public class AuthorServiceTest { @Test public void test_total_book_by_mock() { //1. Setup AuthorServiceImpl obj = new AuthorServiceImpl(); BookServiceImpl bookService = new BookServiceImpl(); bookService.setBookDao(new BookDaoImpl()); //Where Dao connect to? obj.setBookService(bookService); obj.setBookValidatorService(new FakeBookValidatorService()); //2. Test method int qty = obj.getTotalBooks("mkyong"); //3. Verify result assertThat(qty, is(2)); } }
Чтобы пройти вышеуказанный модульный тест, вам необходимо настроить базу данных на уровне DAO, иначе служба бронирования
ничего не вернет.
2.3 Некоторые недостатки при выполнении тестов, подобных приведенным выше:
- Этот модульный тест выполняется медленно, потому что вам нужно запустить базу данных, чтобы получить данные из DAO.
- Этот модульный тест не изолирован, он всегда зависит от внешних ресурсов, таких как база данных.
- Этот модульный тест не может гарантировать, что условия тестирования всегда одинаковы, данные в базе данных могут меняться со временем.
- Слишком много работы, чтобы протестировать простой метод, из-за чего разработчики пропускают тест.
2.4 Решение Решение очевидно, вам нужна модифицированная версия класса BookServiceImpl
, которая всегда будет возвращать одни и те же данные для тестирования, макет объекта !
3. Модульный тест –Макет объекта
3.1 Создайте новый Макет класса BookServiceImpl
и всегда возвращайте одну и ту же коллекцию книг для автора “mkyong”.
package com.mkyong.mock; import com.mkyong.examples.mock.Book; import com.mkyong.examples.mock.BookService; import java.util.ArrayList; import java.util.List; //I am a mock object! public class MockBookServiceImpl implements BookService { @Override public ListfindBookByAuthor(String author) { List books = new ArrayList<>(); if ("mkyong".equals(author)) { books.add(new Book("mkyong in action")); books.add(new Book("abc in action")); books.add(new Book("bot")); } return books; } //implements other methods... }
3.2 Снова обновите модульный тест.
package com.mkyong.mock; import com.mkyong.examples.mock.AuthorServiceImpl; import com.mkyong.examples.mock.FakeBookValidatorService; import org.junit.Test; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; public class AuthorServiceTest { @Test public void test_total_book_by_mock() { //1. Setup AuthorServiceImpl obj = new AuthorServiceImpl(); /*BookServiceImpl bookService = new BookServiceImpl(); bookService.setBookDao(new BookDaoImpl()); obj.setBookService(bookService);*/ obj.setBookService(new MockBookServiceImpl()); obj.setBookValidatorService(new FakeBookValidatorService()); //2. Test method int qty = obj.getTotalBooks("mkyong"); //3. Verify result assertThat(qty, is(2)); } }
Приведенный выше модульный тест намного лучше, быстр, изолирован (больше нет базы данных), и условия тестирования (данные) всегда одинаковы.
3.3 Но есть некоторые недостатки в создании макета объекта вручную, как описано выше:
- В конце вы можете создать множество макетных объектов (классов), просто для целей модульного тестирования.
- Если интерфейс содержит много методов, вам необходимо переопределить каждый из них.
- Это все еще слишком много работы и грязно!
3.4 Решение Попробуй Mockito , простой и мощный фреймворк для насмешек.
4. Модульный тест – Mockito
4.1 Снова обновите модульный тест, на этот раз создайте макет объекта с помощью платформы Mockito.
org.mockito mockito-core 2.0.73-beta
package com.mkyong.mock; import com.mkyong.examples.mock.AuthorServiceImpl; import com.mkyong.examples.mock.Book; import com.mkyong.examples.mock.BookServiceImpl; import com.mkyong.examples.mock.FakeBookValidatorService; import org.junit.Test; import java.util.Arrays; import java.util.List; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class AuthorServiceTest { @Test public void test_total_book_by_mockito() { //1. Setup Listbooks = Arrays.asList( new Book("mkyong in action"), new Book("abc in action"), new Book("bot")); BookServiceImpl mockito = mock(BookServiceImpl.class); //if the author is "mkyong", then return a 'books' object. when(mockito.findBookByAuthor("mkyong")).thenReturn(books); AuthorServiceImpl obj = new AuthorServiceImpl(); obj.setBookService(mockito); obj.setBookValidatorService(new FakeBookValidatorService()); //2. Test method int qty = obj.getTotalBooks("mkyong"); //3. Verify result assertThat(qty, is(2)); } }
Сделано. Мы будем признательны за ваши отзывы
Рекомендации
Оригинал: “https://mkyong.com/unittest/unit-test-what-is-mocking-and-why/”