Форум программистов, компьютерный форум, киберфорум
Наши страницы
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
Lokki23
0 / 0 / 1
Регистрация: 16.11.2014
Сообщений: 85
1

Junit and Mockito тесты

18.05.2016, 14:22. Просмотров 1500. Ответов 18
Метки нет (Все метки)

Добрый день

Мне тут задали некоторое небольшое задание сделать.
Почти сделел только остались тесты.

Но мне нужен взгляд со стороны. Мне кажется что сделоно неплохо но явно чего-то не хватает.

Кину задание ну и мою реализацию. Можите одним глазком посмотреть.

Задание: Implement a simple point of sale.

Assume you have:
– one input device: bar codes scanner
– two output devices: LCD display and printer

Implement:
– single product sale: products bar code is scanned and:
– if the product is found in products database than it's name and price is printed on LCD
– if the product is not found than error message 'Product not found' is printed on LCD
– if the code scanned is empty than error message 'Invalid bar-code' is printed on LCD
– when 'exit' is input than receipt is printed on printer containing a list of all previously scanned items names and prices as well as total sum to be paid for all items; the total sum is also printed on LCD display

Rules:
– use only SDK classes and your favorite test libraries
– mock/stub the database and IO devices
– concentrate on proper design and clean code, rather than supplying fully functioning application

Реализация:
Класс SalePoint
Java
1
2
3
4
5
6
7
8
9
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
public class SalePoint {
    private DBWorker dbWorker = new DBWorker();
    private LCDDisplay lcdDisplay = new LCDDisplay();
    private Printer printer = new Printer();
    private CodesScanner codesScanner = new CodesScanner();
 
    List<Product> list = new ArrayList<Product>();
 
    public SalePoint() throws SQLException {
    }
 
    public boolean hasNextBarCode() {
        return codesScanner.next();
    }
 
    public void calculateLastBarCodeFromScanner() {
        try {
            Product product = null;
            String barCode = codesScanner.getLastBarCode();
 
            switch (barCode) {
                case "":
                    lcdDisplay.showMessage("Product not found");
                    break;
                case "exit":
                    printProducts();
                    return;
                default:
                    product = dbWorker.findProduct(barCode);
 
                    if (product == null) {
                        lcdDisplay.showMessage("Invalid bar-code");
                    }
 
                    lcdDisplay.showProduct(product);
                    list.add(product);
            }
 
        } catch (EmptyStackException e) {
            e.printStackTrace();
        }
    }
 
    private void printProducts() {
        double summ = 0.0;
        for (Product product :
                list) {
            summ += product.getPrice();
        }
        printer.printProductsAndTotalPrice(list, summ);
    }
}
Класс DBWorker
Java
1
2
3
4
5
6
7
8
9
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
public class DBWorker {
    private static String URL = "jdbc:mysql://localhost:3306/mydbtest";
    private static String USERNAME = "root";
    private static String PASSWORD = "root";
    private static String SELECT = "SELECT product_name, price, bar_code FROM products WHERE bar_code = ?;";
 
    private Connection connection;
 
    public DBWorker() throws SQLException {
        Driver driver = new FabricMySQLDriver();
        DriverManager.registerDriver(driver);
 
        connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
    }
 
    public Product findProduct(String barCode) {
        Product product = null;
 
        PreparedStatement preparedStatement = null;
        try {
            preparedStatement = connection.prepareStatement(SELECT);
 
            preparedStatement.setString(1, barCode);
 
            ResultSet resultSet = preparedStatement.executeQuery();
 
            if(resultSet.next())
                product = new Product(resultSet.getString("product_name"), resultSet.getInt("price"), resultSet.getString("bar_code"));
 
        } catch (SQLException e) {
            e.printStackTrace();
        }
 
        return product;
    }
}
Класс CodesScanner
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class CodesScanner {
    Stack<String> barCodeList = new Stack<String>();
 
    public CodesScanner() {
    }
 
    public String getLastBarCode() throws EmptyStackException {
        return barCodeList.pop();
    }
 
    public void scanBarCode(String barCode) {
        barCodeList.push(barCode);
    }
 
    public Boolean next(){
        return barCodeList.isEmpty() == true ? false : true;
    }
}
Класс LCDDisplay
Java
1
2
3
4
5
6
7
8
9
10
11
public class LCDDisplay {
    public LCDDisplay() {
    }
 
    public void showProduct(Product product){
        System.out.println(product.getName() + "\t\t" + product.getPrice());
    }
    public void showMessage(String message){
        System.out.println(message);
    }
}
Класс Priner
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Printer {
    public Printer() {
    }
 
    public void printProducts(List<Product> productList){
        System.out.println("List of products:");
        for (Product product:
             productList) {
            System.out.println(product.getName() + "\t\t\t" + product.getPrice());
        }
    }
 
    public void printProductsAndTotalPrice(List<Product> productList, double totalPrice){
        System.out.println("List of products:\nName\t\t\tPrice");
        for (Product product:
                productList) {
            System.out.println(product.getName() + "\t\t\t" + product.getPrice());
        }
        System.out.println("Total:\t\t\t" + totalPrice);
    }
}
Ну и последний класс Product
Java
1
2
3
4
5
6
7
8
9
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
56
57
58
59
60
61
62
63
64
65
public class Product {
    private String name;
    private double price;
    private String barCode;
 
    public Product(String name, double price, String barCode) {
        this.name = name;
        this.price = price;
        this.barCode = barCode;
    }
 
    public Product() {
    }
 
    public Product(Product obj){
        this(obj.getName(), obj.getPrice(), obj.getBarCode());
    }
 
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
 
        Product product = (Product) o;
 
        if (Double.compare(product.price, price) != 0) return false;
        if (name != null ? !name.equals(product.name) : product.name != null) return false;
        return barCode != null ? barCode.equals(product.barCode) : product.barCode == null;
 
    }
 
    @Override
    public String toString() {
        return "Product{" +
                "name='" + name + '\'' +
                ", price=" + price +
                ", barCode='" + barCode + '\'' +
                '}';
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public double getPrice() {
        return price;
    }
 
    public String getBarCode() {
        return barCode;
    }
 
    public void setBarCode(String barCode) {
        this.barCode = barCode;
    }
 
    public void setPrice(double price) {
        this.price = price;
    }
}
Извините за много кода.

Как на ваш взгляд что нужно доделать или переделать?

Да и по поводу тестирования пока смог написать только это:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
 
    private static final Product PRODUCT = new Product("beer", 2.3, "0000000001");
    private static final String BAR_CODE = "0000000001";
@Test
    public void testFindProduct(){
        DBWorker dbWorker = mock(DBWorker.class);
 
        when(dbWorker.findProduct(BAR_CODE)).thenReturn(new Product("beer", 2.3, "0000000001"));
 
        Product product = dbWorker.findProduct(BAR_CODE);
 
        Assert.assertEquals(product, PRODUCT);
    }
0
Лучшие ответы (1)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.05.2016, 14:22
Ответы с готовыми решениями:

JUnit тесты
Доброго времени суток, знатоки. :) Написал незамысловатый код по заданию, заказчик просит юнит...

JUnit. Как написать тесты, работающие с БД
Добрый день. Подскажите пожалуйста как правильно писать юнит тесты для методов которые открывают и...

JUnit тесты. Параметры в тестовом методе
Задача примерно следующуая. Предположим я написал функцию, которая тестирует класс с параметром...

Junit тесты: как правильно реализовать проверку метода findAll?
Доброго времени суток, форумчане. Подскажите пожалуйста, как правильно реализовать проверку метода...

JUnit тесты
Мне нужно сделать тесты к проекту, собранному в Maven. Не понимаю, как создать тест. У меня в...

18
KEKCoGEN
Эксперт Java
2266 / 2110 / 539
Регистрация: 28.12.2010
Сообщений: 8,322
18.05.2016, 16:21 2
Цитата Сообщение от Lokki23 Посмотреть сообщение
Как на ваш взгляд что нужно доделать или переделать?
Я бы переделал все т.к тут все очень плохо. Задание проверяет ваше понимание ООП и архитектуры приложения. Ни того ни другого тут нет. Так же на некоторые пункты вы просто забили...
Зачем вы БД прикрутили сюда? Вам прямым текстом написано использовать стаб БД.

Причем тут вообще мокито и джюнит в названии темы если вы хотите мнения про код?

Тест единственный что есть тоже ни о чем.

Как вы вообще все это запускаете? Где мейн?
0
Lokki23
0 / 0 / 1
Регистрация: 16.11.2014
Сообщений: 85
18.05.2016, 17:44  [ТС] 3
Можите кратко описать как должно все быть? Я по поводу ООП и архитектуры приложения.
0
KEKCoGEN
Эксперт Java
2266 / 2110 / 539
Регистрация: 28.12.2010
Сообщений: 8,322
18.05.2016, 17:55 4
Lokki23, давайте лучше наоборот. Вы напишите дизайн с описанием классов, flow chart и class diagram а я посоветую что где подправить и улучшить
0
18.05.2016, 17:55
Lokki23
0 / 0 / 1
Регистрация: 16.11.2014
Сообщений: 85
18.05.2016, 18:35  [ТС] 5
Хорошо.
0
Lokki23
0 / 0 / 1
Регистрация: 16.11.2014
Сообщений: 85
19.05.2016, 02:16  [ТС] 6
Пока набросал только flowChart диагаму.
0
Миниатюры
Junit and Mockito тесты  
Lokki23
0 / 0 / 1
Регистрация: 16.11.2014
Сообщений: 85
19.05.2016, 02:30  [ТС] 7
Не имею опыта в рисовании диагарам. Так что выглядит она довольно убого.

Не знаю что и какие методы реализовать в salePoint. Если правильно рассуждаю то когда на входе в Сканере есть сигнал то мы его обрабатываем. То есть нужно зациклить или нет?

C++
1
2
3
4
5
6
7
void run(){
while(1){
while(scanner.next()){
// do something with bar code
}
}
}
0
Миниатюры
Junit and Mockito тесты  
KEKCoGEN
Эксперт Java
2266 / 2110 / 539
Регистрация: 28.12.2010
Сообщений: 8,322
19.05.2016, 08:29 8
Lokki23, flowChart неплохо было бы написать с использованием уже ваших классов из диаграмы.
Уже по диаграме видно где можно улучшить.
У вас есть монитор и принтер. Они оба устройства вывода. Логично бы было создать интерфейс устройства вывода и работать с ним чтобы программа была более гибкой и можно бы было легко заменить устройство вывода. Так же можно поступить и с устройством ввода. И с базой данных. То есть ваша программа (класс сейлпоинт) должна как можно больше работать с интерфейсами. Таким образом поменять хранилище продуктов, устройства ввода\вывода будет легко. Так же такую архитектуру будет легко тестировать.
0
Lokki23
0 / 0 / 1
Регистрация: 16.11.2014
Сообщений: 85
19.05.2016, 16:19  [ТС] 9
Так пойдет?

Да а как сделать тесты? Например использовать стаб БД?

И в PointSale:

C++
1
2
3
    private InputDevice codesScanner = new CodesScanner();
    private OutputDevice lcdDisplay = new LCDDisplay();
    private OutputDevice printer = new Printer();
0
Миниатюры
Junit and Mockito тесты  
KEKCoGEN
Эксперт Java
2266 / 2110 / 539
Регистрация: 28.12.2010
Сообщений: 8,322
19.05.2016, 16:29 10
Lokki23, вам в вашем решении вообще ненужна БД. Забудьте про неё. Почему интпуд девайс у вас обладает методом write и методом hasNext? Девайс должен только получать на вход баркод и возвращать продукт или выбрасывать исключение если произошла ошибка
0
Lokki23
0 / 0 / 1
Регистрация: 16.11.2014
Сообщений: 85
19.05.2016, 16:58  [ТС] 11
У меня метод write - это вход.

Просто я думал следующим образом:

1) Input Device считует баркод(метод write(barcode:string))
2) Потом с каласа PoinSale мы проверяем есть ли считаный бар-код и делаем что-то.... - исчим в базе продукт пишем на екране ну и принтере.

Просто я думаю что inputdevice не должен иметь доступ к базе наших продуктов, а только класс PoinSale?
0
KEKCoGEN
Эксперт Java
2266 / 2110 / 539
Регистрация: 28.12.2010
Сообщений: 8,322
20.05.2016, 14:18 12
Цитата Сообщение от Lokki23 Посмотреть сообщение
Input Device считует баркод(метод write(barcode:string))
не лучше ли метод чтение назвать read а не write?

Цитата Сообщение от Lokki23 Посмотреть сообщение
Просто я думаю что inputdevice не должен иметь доступ к базе наших продуктов
Он может иметь доступ к интерфейсу inventory например.

Вы знакомы с шаблонами проектирования? Неплохо было бы почитать и применять
0
Lokki23
0 / 0 / 1
Регистрация: 16.11.2014
Сообщений: 85
20.05.2016, 17:46  [ТС] 13
Ну ок.

Хотел спросить о тестировании.
Можно ли каким-то образом получить доступ к объекту?


Например:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    @Test
    public void testPointOfSale(){
        SalePoint salePoint = spy(new SalePoint());
 
    public void testPointOfSale(){
        SalePoint salePoint = spy(new SalePoint());
 
        // чтоб написать следующим образом
 
        when(salePoint.codesScaner.read()).thenReturn("barcode");
 
 
        // Ну и БД соответственно
 
        when(salePoint.dbWorker.findProduct()).thenReturn(new Product("beer", 2.3, "0000000001"));
    }
 
    }
codesScabner и dbWorker соответственно приваты. Ести ли смысл делать их паблик?
Как можна протестить это дело?
0
KEKCoGEN
Эксперт Java
2266 / 2110 / 539
Регистрация: 28.12.2010
Сообщений: 8,322
20.05.2016, 20:13 14
Цитата Сообщение от Lokki23 Посмотреть сообщение
codesScabner и dbWorker соответственно приваты. Ести ли смысл делать их паблик?
нет.

Цитата Сообщение от Lokki23 Посмотреть сообщение
Как можна протестить это дело?
сначала определите какой функционал вы хотите постетить. Нет смысла тестировать главный класс целиком. Надо тестировать отдельно методы таких классов как сканер например.
0
Lokki23
0 / 0 / 1
Регистрация: 16.11.2014
Сообщений: 85
20.05.2016, 22:17  [ТС] 15
Ну а если так?

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Main {
 
    public static void main(String[] args) {
        InputDevice codesScanner = mock(CodesScanner.class);
        OutputDevice printer = spy(Printer.class);
        OutputDevice lcdDisplay = spy(LCDDisplay.class);
        DBWorker dbWorker = mock(DBWorker.class);
 
        SalePoint salePoint = spy(new SalePoint(codesScanner, lcdDisplay, printer, dbWorker));
 
        when(codesScanner.readLine())
                .thenReturn("0000000001")
                .thenReturn("0000000002")
                .thenReturn("0000000003")
                .thenReturn("0000000004")
                .thenReturn("")
                .thenReturn("exit");
 
        when(dbWorker.findProduct("0000000001")).thenReturn(new Product("apple", 2.1, "0000000001"));
        when(dbWorker.findProduct("0000000002")).thenReturn(new Product("beer", 2.5, "0000000002"));
        when(dbWorker.findProduct("0000000003")).thenReturn(new Product("lemon", 4.0, "0000000003"));
        when(dbWorker.findProduct("0000000004")).thenReturn(null);
 
        salePoint.run();
    }
}
Class SalePoint
Java
1
2
3
4
5
6
7
8
9
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
public class SalePoint {
    private InputDevice codesScanner = null;
    private DBWorker dbWorker = null;
    private OutputDevice lcdDisplay = null;
    private OutputDevice printer = null;
 
    private List<Product> list = new ArrayList<Product>();
 
    public SalePoint(InputDevice codesScanner, OutputDevice lcdDisplay,
                     OutputDevice printer, DBWorker dbWorker){
        this.codesScanner = codesScanner;
        this.lcdDisplay = lcdDisplay;
        this.printer = printer;
        this.dbWorker = dbWorker;
    }
 
 
    public void run() {
        Product product;
        String barCode;
        while((barCode = codesScanner.readLine()) != null) {
 
            switch (barCode) {
                case "":
                    lcdDisplay.printError("Invalid bar-code");
                    break;
                case "exit":
                    printProductsAndTotalPrice();
                    return;
                default:
                    product = dbWorker.findProduct(barCode);
                     if (product == null) {
                         lcdDisplay.printError("Product not found");
                     }else {
                         lcdDisplay.print(product);
                         list.add(product);
                     }
            }
        }
 
    }
 
    private void printProductsAndTotalPrice() {
        double summ = 0.0;
 
        for (Product product :
                list)
            summ += product.getPrice();
 
        printer.println("List of products:");
        printer.println("Name\t\t\tPrice");
        printer.print(list, summ);
        list.clear();
    }
}
Да и бд улалил оставил только

Java
1
2
3
4
5
6
7
8
9
public class DBWorker {
 
    public DBWorker(){
    }
 
    public Product findProduct(String barCode) {
        return null;
    }
}
0
KEKCoGEN
Эксперт Java
2266 / 2110 / 539
Регистрация: 28.12.2010
Сообщений: 8,322
21.05.2016, 01:36 16
Lokki23, у вас какая то каша в голове и из за этого в коде. Зачем вы в мейн понапихали моков всяких? Зачем вы писали дизайн если не делаете по нему? Сдавайте вообщем как есть. На вашем уровне понимания пока что лучше вряд ли выйдет
0
Lokki23
0 / 0 / 1
Регистрация: 16.11.2014
Сообщений: 85
21.05.2016, 14:43  [ТС] 17
Последний вопрос как сделать это – mock/stub the database and IO devices?
0
KEKCoGEN
Эксперт Java
2266 / 2110 / 539
Регистрация: 28.12.2010
Сообщений: 8,322
21.05.2016, 22:16 18
Лучший ответ Сообщение было отмечено Lokki23 как решение

Решение

Lokki23, имеется в виду не подключать реальную БД, а написать какой нибудь класс который будет выдавать продукты. В классе Map держите какой-нибудь и из него выдавайте.
1
Lokki23
0 / 0 / 1
Регистрация: 16.11.2014
Сообщений: 85
21.05.2016, 22:51  [ТС] 19
Ясно. Спасибо за уделенное время.
0
21.05.2016, 22:51
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
21.05.2016, 22:51

На могу запустить Mockito
Установил JUNIT и Mockito. Прописал в джар переменных, импортировал. Но при загрузки тестов...

JUnit тесты для базы данных
Начал осваивать юнит тестирование, и появился один вопрос. BaseDataConnect...

Тестирование с Mockito
Привет, я пытаюсь написать тест для слоя сервиса в своем web приложении, но у меня не получается...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.