Рубрики
Без рубрики

Модульный тест – Что такое издевательство? и почему?

– Модульный тест – Что такое издевательство? и почему?

Автор оригинала: mkyong.

Проще говоря, издевательство – это создание объектов, имитирующих поведение реальных объектов. Обратитесь к следующему тематическому исследованию:

Проверенный:

  1. Java 1.8
  2. Юнит 4.12
  3. Mockito 2.0.73-бета-версия

1. Примеры Java

Простой пример автора и книги.

1.1 Книжный сервис для возврата списка книг по имени автора.

package com.mkyong.examples.mock;

import java.util.List;

public interface BookService {

    List findBookByAuthor(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 List findBookByAuthor(String name) {
        return bookDao.findBookByAuthor(name);
    }

}
package com.mkyong.examples.mock;

import java.util.List;

public interface BookDao {

    List findBookByAuthor(String author);
    
}
package com.mkyong.examples.mock;

import java.util.List;

public class BookDaoImpl implements BookDao {

    @Override
    public List findBookByAuthor(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) {

        List books = 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 Некоторые недостатки при выполнении тестов, подобных приведенным выше:

  1. Этот модульный тест выполняется медленно, потому что вам нужно запустить базу данных, чтобы получить данные из DAO.
  2. Этот модульный тест не изолирован, он всегда зависит от внешних ресурсов, таких как база данных.
  3. Этот модульный тест не может гарантировать, что условия тестирования всегда одинаковы, данные в базе данных могут меняться со временем.
  4. Слишком много работы, чтобы протестировать простой метод, из-за чего разработчики пропускают тест.

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 List findBookByAuthor(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 Но есть некоторые недостатки в создании макета объекта вручную, как описано выше:

  1. В конце вы можете создать множество макетных объектов (классов), просто для целей модульного тестирования.
  2. Если интерфейс содержит много методов, вам необходимо переопределить каждый из них.
  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
	        List books = 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));

	    }

}

Сделано. Мы будем признательны за ваши отзывы

Рекомендации

  1. Официальный сайт Mockito
  2. ДЗоне–Мокито
  3. Википедия – Макет объекта
  4. Модульные тесты с Mockito

Оригинал: “https://mkyong.com/unittest/unit-test-what-is-mocking-and-why/”