diff --git a/README.md b/README.md index 67d4ca0..74e0743 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,12 @@ -# OtusSpringHW -Домашние задания по Spring для Otus. +# OtusSpringHW + +Домашнее задание #2: +- Добавить файл настроек в приложение и для тестирования. +- Локализовать выводимые сообщения и вопросы теста. +- Переписать конфигурацию в виде Java + Annotation-based конфигурации. + +### 19-03-22 Доработки: +- Убраны лишние тесты. +- Изменена работа с файлом. +- Использование @Data вместо @Getter, @Setter. +- Добавлены *.properties для тестов. diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..ae8c2f6 --- /dev/null +++ b/pom.xml @@ -0,0 +1,138 @@ + + + 4.0.0 + + home-work-01 + + ru.otus.mkulikov + home-work + 1.0-SNAPSHOT + + + 11 + ${java.version} + ${java.version} + UTF-8 + + + + + org.springframework + spring-context + 5.0.9.RELEASE + + + + org.springframework + spring-test + 5.0.9.RELEASE + + + + net.sf.opencsv + opencsv + 2.3 + + + + javax.annotation + javax.annotation-api + 1.3.2 + + + + junit + junit + 4.12 + test + + + + org.junit.jupiter + junit-jupiter-api + 5.4.0 + test + + + + org.junit.jupiter + junit-jupiter-engine + 5.4.0 + test + + + + org.assertj + assertj-core + 3.11.1 + test + + + + org.junit.platform + junit-platform-launcher + 1.4.1 + test + + + + org.projectlombok + lombok + 1.18.4 + provided + + + + + org.mockito + mockito-all + 1.10.19 + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + ${encoding} + + + + + org.apache.maven.plugins + maven-resources-plugin + + ${encoding} + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.0 + + + false + + + + + + + src/main/resources + + **/*.csv + **/*.properties + + false + + + + \ No newline at end of file diff --git a/src/main/java/ru/otus/mkulikov/Application.java b/src/main/java/ru/otus/mkulikov/Application.java new file mode 100644 index 0000000..3f6ee5d --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/Application.java @@ -0,0 +1,33 @@ +package ru.otus.mkulikov; + +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import ru.otus.mkulikov.exceptions.QuestionsFileLoadingException; +import ru.otus.mkulikov.services.processor.ProcessorService; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-14 + * Time: 15:27 + */ + +@Configuration +@ComponentScan +@PropertySource("classpath:application.properties") +public class Application { + + public static void main(String[] args) { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class); + try { + ProcessorService processor = context.getBean(ProcessorService.class); + processor.startTest(); + } catch (QuestionsFileLoadingException e) { + e.printStackTrace(); + } finally { + context.close(); + } + } +} diff --git a/src/main/java/ru/otus/mkulikov/exceptions/QuestionsFileLoadingException.java b/src/main/java/ru/otus/mkulikov/exceptions/QuestionsFileLoadingException.java new file mode 100644 index 0000000..2105a5b --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/exceptions/QuestionsFileLoadingException.java @@ -0,0 +1,19 @@ +package ru.otus.mkulikov.exceptions; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-17 + * Time: 01:40 + */ + +public class QuestionsFileLoadingException extends RuntimeException { + + public QuestionsFileLoadingException(String message) { + super(message); + } + + public QuestionsFileLoadingException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/ru/otus/mkulikov/models/Question.java b/src/main/java/ru/otus/mkulikov/models/Question.java new file mode 100644 index 0000000..e148602 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/models/Question.java @@ -0,0 +1,39 @@ +package ru.otus.mkulikov.models; + +import lombok.Data; + +import java.io.Serializable; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-14 + * Time: 15:54 + */ + +@Data +public class Question implements Serializable { + + private String id; + private String question; + private String answer1; + private String answer2; + private String answer3; + private String answer4; + private String trueAnswer; + private String userAnswer; + + public Question(String id, String question, String answer1, String answer2, String answer3, String answer4, String trueAnswer, String userAnswer) { + this.id = id; + this.question = question; + this.answer1 = answer1; + this.answer2 = answer2; + this.answer3 = answer3; + this.answer4 = answer4; + this.trueAnswer = trueAnswer; + this.userAnswer = userAnswer; + } + + public Question() { + } +} diff --git a/src/main/java/ru/otus/mkulikov/models/User.java b/src/main/java/ru/otus/mkulikov/models/User.java new file mode 100644 index 0000000..52a10f1 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/models/User.java @@ -0,0 +1,22 @@ +package ru.otus.mkulikov.models; + +import lombok.Data; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-14 + * Time: 15:29 + */ + +@Data +public class User { + + private final String name; + private final String surname; + + public User(String name, String surname) { + this.name = name; + this.surname = surname; + } +} diff --git a/src/main/java/ru/otus/mkulikov/services/console/ConsoleIOServiceImpl.java b/src/main/java/ru/otus/mkulikov/services/console/ConsoleIOServiceImpl.java new file mode 100644 index 0000000..115a0e1 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/services/console/ConsoleIOServiceImpl.java @@ -0,0 +1,38 @@ +package ru.otus.mkulikov.services.console; + +import org.springframework.stereotype.Service; + +import javax.annotation.PreDestroy; +import java.util.Scanner; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 17.03.2019 + * Time: 23:21 + */ + +@Service +public class ConsoleIOServiceImpl implements IOService { + + private final Scanner in; + + public ConsoleIOServiceImpl() { + in = new Scanner(System.in); + } + + @Override + public void write(String text) { + System.out.println(text); + } + + @Override + public String read() { + return in.nextLine(); + } + + @PreDestroy + public void destroy() { + in.close(); + } +} diff --git a/src/main/java/ru/otus/mkulikov/services/console/IOService.java b/src/main/java/ru/otus/mkulikov/services/console/IOService.java new file mode 100644 index 0000000..b6f92d3 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/services/console/IOService.java @@ -0,0 +1,15 @@ +package ru.otus.mkulikov.services.console; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 17.03.2019 + * Time: 23:21 + */ + +public interface IOService { + + void write(String text); + + String read(); +} diff --git a/src/main/java/ru/otus/mkulikov/services/localisation/LocalisationService.java b/src/main/java/ru/otus/mkulikov/services/localisation/LocalisationService.java new file mode 100644 index 0000000..fa1f7fe --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/services/localisation/LocalisationService.java @@ -0,0 +1,15 @@ +package ru.otus.mkulikov.services.localisation; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-21 + * Time: 14:02 + */ + +public interface LocalisationService { + + String getValue(String key); + + String getValueWithParams(String key, String[] params); +} diff --git a/src/main/java/ru/otus/mkulikov/services/localisation/LocalisationServiceImpl.java b/src/main/java/ru/otus/mkulikov/services/localisation/LocalisationServiceImpl.java new file mode 100644 index 0000000..2af1b75 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/services/localisation/LocalisationServiceImpl.java @@ -0,0 +1,43 @@ +package ru.otus.mkulikov.services.localisation; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.support.ReloadableResourceBundleMessageSource; +import org.springframework.stereotype.Service; + +import java.util.Locale; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-21 + * Time: 14:02 + */ + +@Service +public class LocalisationServiceImpl extends ReloadableResourceBundleMessageSource implements LocalisationService { + + private final Locale locale; + private final Locale russian = new Locale("ru"); + + public LocalisationServiceImpl( + @Value("${locale.basename}") String basename, + @Value("${locale.default.encoding}") String defaultEncoding, + @Value("${locale.default}") String localeDefault + ) { + super(); + setBasename(basename); + setDefaultEncoding(defaultEncoding); + + locale = (localeDefault != null) + ? new Locale(localeDefault) + : russian; + } + + public String getValue(String key) { + return getMessage(key, null, locale); + } + + public String getValueWithParams(String key, String[] params) { + return getMessage(key, params, locale); + } +} diff --git a/src/main/java/ru/otus/mkulikov/services/processor/ProcessorService.java b/src/main/java/ru/otus/mkulikov/services/processor/ProcessorService.java new file mode 100644 index 0000000..bfb3896 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/services/processor/ProcessorService.java @@ -0,0 +1,13 @@ +package ru.otus.mkulikov.services.processor; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-14 + * Time: 15:54 + */ + +public interface ProcessorService { + + void startTest(); +} diff --git a/src/main/java/ru/otus/mkulikov/services/processor/ProcessorServiceImpl.java b/src/main/java/ru/otus/mkulikov/services/processor/ProcessorServiceImpl.java new file mode 100644 index 0000000..50a00aa --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/services/processor/ProcessorServiceImpl.java @@ -0,0 +1,32 @@ +package ru.otus.mkulikov.services.processor; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.otus.mkulikov.services.questions.QuestionsService; +import ru.otus.mkulikov.services.registration.RegistrationService; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-14 + * Time: 15:54 + */ + +@Service +public class ProcessorServiceImpl implements ProcessorService { + + private final QuestionsService questionsService; + private final RegistrationService registration; + + @Autowired + public ProcessorServiceImpl(QuestionsService questionsService, RegistrationService registration) { + this.questionsService = questionsService; + this.registration = registration; + } + + @Override + public void startTest() { + registration.addNewUser(); + questionsService.showQuestions(); + } +} diff --git a/src/main/java/ru/otus/mkulikov/services/questions/QuestionsService.java b/src/main/java/ru/otus/mkulikov/services/questions/QuestionsService.java new file mode 100644 index 0000000..15fd4bb --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/services/questions/QuestionsService.java @@ -0,0 +1,15 @@ +package ru.otus.mkulikov.services.questions; + +import ru.otus.mkulikov.exceptions.QuestionsFileLoadingException; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-14 + * Time: 16:41 + */ + +public interface QuestionsService { + + void showQuestions() throws QuestionsFileLoadingException; +} diff --git a/src/main/java/ru/otus/mkulikov/services/questions/QuestionsServiceImpl.java b/src/main/java/ru/otus/mkulikov/services/questions/QuestionsServiceImpl.java new file mode 100644 index 0000000..672ff7e --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/services/questions/QuestionsServiceImpl.java @@ -0,0 +1,75 @@ +package ru.otus.mkulikov.services.questions; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.otus.mkulikov.exceptions.QuestionsFileLoadingException; +import ru.otus.mkulikov.models.Question; +import ru.otus.mkulikov.services.console.IOService; +import ru.otus.mkulikov.services.localisation.LocalisationService; +import ru.otus.mkulikov.services.questions.dao.QuestionsDAO; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-14 + * Time: 16:41 + */ + +@Service +public class QuestionsServiceImpl implements QuestionsService { + + private final String c_delimeter = "---------------------------------------------------"; + private final String c_answerNumbers = "1234"; + + private final QuestionsDAO questionsDAO; + private final IOService consoleService; + private final LocalisationService localisationService; + + @Autowired + public QuestionsServiceImpl(QuestionsDAO questionsDAO, IOService consoleService, LocalisationService localisationService) { + this.questionsDAO = questionsDAO; + this.consoleService = consoleService; + this.localisationService = localisationService; + } + + @Override + public void showQuestions() throws QuestionsFileLoadingException { + consoleService.write(c_delimeter); + List questions = questionsDAO.getQuestions(); + + for (Question question : questions) { + consoleService.write(question.getQuestion()); + consoleService.write(question.getAnswer1()); + consoleService.write(question.getAnswer2()); + consoleService.write(question.getAnswer3()); + consoleService.write(question.getAnswer4()); + + String answer = null; + boolean okAnswer = false; + int i = 0; + while (!okAnswer && i < 4) { + consoleService.write(localisationService.getValue("enter.answer")); + answer = consoleService.read(); + okAnswer = c_answerNumbers.contains(answer) && !answer.isEmpty(); + i++; + } + + question.setUserAnswer((!okAnswer && i == 4) ? "0" : answer); + consoleService.write(c_delimeter); + } + + long count = questions.stream() + .filter(obj -> obj.getTrueAnswer().equals(obj.getUserAnswer())) + .count(); + + consoleService.write( + localisationService.getValueWithParams( + "count.true.answers", + new String[] {String.valueOf(count), String.valueOf(questions.size())} + ) + ); + consoleService.write(c_delimeter); + } +} diff --git a/src/main/java/ru/otus/mkulikov/services/questions/dao/QuestionsDAO.java b/src/main/java/ru/otus/mkulikov/services/questions/dao/QuestionsDAO.java new file mode 100644 index 0000000..96beeeb --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/services/questions/dao/QuestionsDAO.java @@ -0,0 +1,18 @@ +package ru.otus.mkulikov.services.questions.dao; + +import ru.otus.mkulikov.exceptions.QuestionsFileLoadingException; +import ru.otus.mkulikov.models.Question; + +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-14 + * Time: 16:41 + */ + +public interface QuestionsDAO { + + List getQuestions() throws QuestionsFileLoadingException; +} diff --git a/src/main/java/ru/otus/mkulikov/services/questions/dao/QuestionsDAOImpl.java b/src/main/java/ru/otus/mkulikov/services/questions/dao/QuestionsDAOImpl.java new file mode 100644 index 0000000..eb09c51 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/services/questions/dao/QuestionsDAOImpl.java @@ -0,0 +1,67 @@ +package ru.otus.mkulikov.services.questions.dao; + +import au.com.bytecode.opencsv.CSVReader; +import au.com.bytecode.opencsv.bean.ColumnPositionMappingStrategy; +import au.com.bytecode.opencsv.bean.CsvToBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.ClassPathResource; +import org.springframework.stereotype.Repository; +import ru.otus.mkulikov.exceptions.QuestionsFileLoadingException; +import ru.otus.mkulikov.models.Question; +import ru.otus.mkulikov.services.localisation.LocalisationService; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.List; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-14 + * Time: 16:42 + */ + +@Repository +public class QuestionsDAOImpl implements QuestionsDAO { + + private final LocalisationService localisationService; + private final String defaultFileDir; + + public QuestionsDAOImpl( + LocalisationService localisationService, + @Value("${questions.default.dir}") String defaultFileDir + ) { + this.localisationService = localisationService; + this.defaultFileDir = defaultFileDir; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Override + public List getQuestions() throws QuestionsFileLoadingException { + String csvFilename = defaultFileDir + "/" + localisationService.getValue("csv.file.name"); + List questions; + try { + ClassPathResource resource = new ClassPathResource(csvFilename); + CSVReader csvReader = new CSVReader(new InputStreamReader(resource.getInputStream(), "UTF-8")); + questions = new CsvToBean().parse(setColumMapping(), csvReader); + } catch (FileNotFoundException e) { + throw new QuestionsFileLoadingException(localisationService.getValueWithParams("questions.find.error.filename", new String[] {csvFilename}), e); + } catch (UnsupportedEncodingException e) { + throw new QuestionsFileLoadingException(localisationService.getValue("questions.encoding.error"), e); + } catch (IOException e) { + throw new QuestionsFileLoadingException(localisationService.getValue("questions.io.error"), e); + } + return questions; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + private ColumnPositionMappingStrategy setColumMapping() { + ColumnPositionMappingStrategy strategy = new ColumnPositionMappingStrategy(); + strategy.setType(Question.class); + String[] columns = new String[]{"id", "question", "answer1", "answer2", "answer3", "answer4", "trueAnswer"}; + strategy.setColumnMapping(columns); + return strategy; + } +} diff --git a/src/main/java/ru/otus/mkulikov/services/registration/RegistrationService.java b/src/main/java/ru/otus/mkulikov/services/registration/RegistrationService.java new file mode 100644 index 0000000..8e0d4e1 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/services/registration/RegistrationService.java @@ -0,0 +1,13 @@ +package ru.otus.mkulikov.services.registration; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-14 + * Time: 16:34 + */ + +public interface RegistrationService { + + void addNewUser(); +} diff --git a/src/main/java/ru/otus/mkulikov/services/registration/RegistrationServiceImpl.java b/src/main/java/ru/otus/mkulikov/services/registration/RegistrationServiceImpl.java new file mode 100644 index 0000000..08c64a0 --- /dev/null +++ b/src/main/java/ru/otus/mkulikov/services/registration/RegistrationServiceImpl.java @@ -0,0 +1,42 @@ +package ru.otus.mkulikov.services.registration; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.otus.mkulikov.models.User; +import ru.otus.mkulikov.services.console.IOService; +import ru.otus.mkulikov.services.localisation.LocalisationService; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-14 + * Time: 16:34 + */ + +@Service +public class RegistrationServiceImpl implements RegistrationService { + + private final IOService consoleService; + private final LocalisationService localisationService; + + @Autowired + public RegistrationServiceImpl(IOService consoleService, LocalisationService localisationService) { + this.consoleService = consoleService; + this.localisationService = localisationService; + } + + @Override + public void addNewUser() { + consoleService.write(localisationService.getValue("enter.your.data")); + consoleService.write(localisationService.getValue("enter.your.surname")); + String surname = consoleService.read(); + + consoleService.write(localisationService.getValue("enter.your.name")); + String name = consoleService.read(); + + User user = new User(name, surname); + consoleService.write( + localisationService.getValueWithParams("hello.user", new String[] {user.getName(), user.getSurname()}) + ); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..c6450d1 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,5 @@ +locale.basename=/i18n/bundle +locale.default.encoding=UTF-8 +locale.default=ru + +questions.default.dir=/questions \ No newline at end of file diff --git a/src/main/resources/i18n/bundle_en.properties b/src/main/resources/i18n/bundle_en.properties new file mode 100644 index 0000000..9907680 --- /dev/null +++ b/src/main/resources/i18n/bundle_en.properties @@ -0,0 +1,11 @@ +count.true.answers=Number of correct answers: {0} of {1} +enter.answer=Enter answer number: +enter.your.data=Enter your data +enter.your.name=Name: +enter.your.surname=Surname: +hello.user=Hello, {0} {1}! +questions.encoding.error=File encoding error! +questions.find.error.filename=File named {0} not found! +questions.io.error=Error I/O when working with a file! + +csv.file.name=en.csv diff --git a/src/main/resources/i18n/bundle_ru.properties b/src/main/resources/i18n/bundle_ru.properties new file mode 100644 index 0000000..5ff9c0a --- /dev/null +++ b/src/main/resources/i18n/bundle_ru.properties @@ -0,0 +1,11 @@ +count.true.answers=Количество правильных ответов: {0} из {1} +enter.answer=Введите номер ответа: +enter.your.data=Введите свои данные +enter.your.name=Имя: +enter.your.surname=Фамилия: +hello.user=Здравствуйте, {0} {1}! +questions.encoding.error=Ошибка кодировки файла! +questions.find.error.filename=Файл с именем {0} не найден! +questions.io.error=Ошибка ввода/вывода при работе с файлом! + +csv.file.name=ru.csv diff --git a/src/main/resources/questions/en.csv b/src/main/resources/questions/en.csv new file mode 100644 index 0000000..4d91327 --- /dev/null +++ b/src/main/resources/questions/en.csv @@ -0,0 +1,5 @@ +1,Which list is not a design pattern?,1. Facade,2. Object,3. Factory,4. Singleton,2 +2,Which type is not primitive?,1. String,2. int,3. char,4. boolean,1 +3,How many classes can be inherited in Java?,1. One,2. Two,3. Three,4. Four,1 +4,Which collection contains unique objects?,1. List,2. Map,3. Set,4. Queue,3 +5,What value cannot be put in the primitive type - int?,1. -1,2. 0,3. 10,4. null,4 \ No newline at end of file diff --git a/src/main/resources/questions/ru.csv b/src/main/resources/questions/ru.csv new file mode 100644 index 0000000..6114d64 --- /dev/null +++ b/src/main/resources/questions/ru.csv @@ -0,0 +1,5 @@ +1,Что из списка не является паттерном проектирования?,1. Фасад,2. Объект,3. Фабрика,4. Синглтон,2 +2,Какой тип не является примитивным?,1. String,2. int,3. char,4. boolean,1 +3,Сколько классов можно наследовать в Java?,1. Один,2. Два,3. Три,4. Четыре,1 +4,Какая коллекция содержит уникальне объекты?,1. List,2. Map,3. Set,4. Queue,3 +5,Какое значение нельзя положить в примитивный тип - int?,1. -1,2. 0,3. 10,4. null,4 \ No newline at end of file diff --git a/src/test/java/ru/otus/mkulikov/questions/QuestionsDAOTest.java b/src/test/java/ru/otus/mkulikov/questions/QuestionsDAOTest.java new file mode 100644 index 0000000..a9bb600 --- /dev/null +++ b/src/test/java/ru/otus/mkulikov/questions/QuestionsDAOTest.java @@ -0,0 +1,59 @@ +package ru.otus.mkulikov.questions; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import ru.otus.mkulikov.Application; +import ru.otus.mkulikov.exceptions.QuestionsFileLoadingException; +import ru.otus.mkulikov.models.Question; +import ru.otus.mkulikov.services.localisation.LocalisationServiceImpl; +import ru.otus.mkulikov.services.questions.dao.QuestionsDAO; +import ru.otus.mkulikov.services.questions.dao.QuestionsDAOImpl; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@DisplayName("Класс QuestionsDAO") +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = Application.class) +@TestPropertySource("/test.properties") +class QuestionsDAOTest { + + @Value("${test.basename}") + private String folder; + @Value("${test.default.encoding}") + private String encoding; + @Value("${test.default.ru}") + private String ru; + @Value("${test.default.en}") + private String en; + @Value("${test.question.folder}") + private String questionFolder; + + private final String c_test1 = "Тест1"; + private final String c_test2 = "Тест2"; + private final String c_test3 = "Тест3"; + + @Test + @DisplayName("Корректная загрузка вопросов") + public void loadQuestionsTest() throws QuestionsFileLoadingException { + LocalisationServiceImpl localisationService = new LocalisationServiceImpl(folder, encoding, ru); + QuestionsDAO questionsDAO = new QuestionsDAOImpl(localisationService, questionFolder); + + List questions = questionsDAO.getQuestions(); + + assertAll("questions", + () -> assertNotNull(questions), + () -> assertEquals(3, questions.size()), + () -> assertEquals(c_test1, questions.get(0).getQuestion()), + () -> assertEquals(c_test2, questions.get(1).getQuestion()), + () -> assertEquals(c_test3, questions.get(2).getQuestion()) + ); + } +} \ No newline at end of file diff --git a/src/test/java/ru/otus/mkulikov/services/localisation/LocalisationServiceImplTest.java b/src/test/java/ru/otus/mkulikov/services/localisation/LocalisationServiceImplTest.java new file mode 100644 index 0000000..2984838 --- /dev/null +++ b/src/test/java/ru/otus/mkulikov/services/localisation/LocalisationServiceImplTest.java @@ -0,0 +1,84 @@ +package ru.otus.mkulikov.services.localisation; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import ru.otus.mkulikov.Application; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Created by IntelliJ IDEA. + * Developer: Maksim Kulikov + * Date: 2019-03-22 + * Time: 13:58 + */ + +@DisplayName("Класс LocalisationServiceImpl") +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = Application.class) +@TestPropertySource("/test.properties") +class LocalisationServiceImplTest { + + @Value("${test.basename}") + private String folder; + @Value("${test.default.encoding}") + private String encoding; + @Value("${test.default.ru}") + private String ru; + @Value("${test.default.en}") + private String en; + + @Test + @DisplayName("Проверка получения значения ru локали") + void getValueRuTest() { + LocalisationService ruLocale = new LocalisationServiceImpl(folder, encoding, ru); + String value = ruLocale.getValue("test.key"); + + assertAll("value", + () -> assertNotNull(value), + () -> assertEquals("тест123", value) + ); + } + + @Test + @DisplayName("Проверка получения значения en локали") + void getValueEnTest() { + LocalisationService enLocale = new LocalisationServiceImpl(folder, encoding, en); + String value = enLocale.getValue("test.key"); + + assertAll("value", + () -> assertNotNull(value), + () -> assertEquals("test123", value) + ); + } + + @Test + @DisplayName("Проверка получения значения ru локали с параметром") + void getValueRuWithParamsTest() { + LocalisationService ruLocale = new LocalisationServiceImpl(folder, encoding, ru); + String value = ruLocale.getValueWithParams("test.key.params", new String[]{"При", "вет"}); + + assertAll("value", + () -> assertNotNull(value), + () -> assertEquals("При и вет - Привет", value) + ); + } + + @Test + @DisplayName("Проверка получения значения en локали с параметром") + void getValueEnWithParamsTest() { + LocalisationService enLocale = new LocalisationServiceImpl(folder, encoding, en); + String value = enLocale.getValueWithParams("test.key.params", new String[]{"Hel", "lo"}); + + assertAll("value", + () -> assertNotNull(value), + () -> assertEquals("Hel & lo - Hello", value) + ); + } +} \ No newline at end of file diff --git a/src/test/resources/locale/bundle_en.properties b/src/test/resources/locale/bundle_en.properties new file mode 100644 index 0000000..4c04204 --- /dev/null +++ b/src/test/resources/locale/bundle_en.properties @@ -0,0 +1,14 @@ +count.true.answers=Number of correct answers: {0} of {1} +enter.answer=Enter answer number: +enter.your.data=Enter your data +enter.your.name=Name: +enter.your.surname=Surname: +hello.user=Hello, {0} {1}! +questions.encoding.error=File encoding error! +questions.find.error.filename=File named {0} not found! +questions.io.error=Error I/O when working with a file! + +csv.file.name=en.csv + +test.key=test123 +test.key.params={0} & {1} - Hello \ No newline at end of file diff --git a/src/test/resources/locale/bundle_ru.properties b/src/test/resources/locale/bundle_ru.properties new file mode 100644 index 0000000..2fc5bc9 --- /dev/null +++ b/src/test/resources/locale/bundle_ru.properties @@ -0,0 +1,14 @@ +count.true.answers=Количество правильных ответов: {0} из {1} +enter.answer=Введите номер ответа: +enter.your.data=Введите свои данные +enter.your.name=Имя: +enter.your.surname=Фамилия: +hello.user=Здравствуйте, {0} {1}! +questions.encoding.error=Ошибка кодировки файла! +questions.find.error.filename=Файл с именем {0} не найден! +questions.io.error=Ошибка ввода/вывода при работе с файлом! + +csv.file.name=ru.csv + +test.key=тест123 +test.key.params={0} и {1} - Привет \ No newline at end of file diff --git a/src/test/resources/questions/ru.csv b/src/test/resources/questions/ru.csv new file mode 100644 index 0000000..47cc49f --- /dev/null +++ b/src/test/resources/questions/ru.csv @@ -0,0 +1,3 @@ +1,Тест1,Ответ1,Ответ2,Ответ3,Ответ4,Ответ1 +2,Тест2,Ответ1,Ответ2,Ответ3,Ответ4,Ответ1 +3,Тест3,Ответ1,Ответ2,Ответ3,Ответ4,Ответ1 diff --git a/src/test/resources/test.properties b/src/test/resources/test.properties new file mode 100644 index 0000000..ea04e2e --- /dev/null +++ b/src/test/resources/test.properties @@ -0,0 +1,6 @@ +test.basename=/locale/bundle +test.default.encoding=UTF-8 +test.default.ru=ru +test.default.en=en + +test.question.folder=/questions