Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,20 @@ repositories {
}

dependencies {
testImplementation 'org.mockito:mockito-core:5.14.2'
testImplementation 'org.mockito:mockito-junit-jupiter:5.14.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.11.4'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.11.4'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.11.4'
}

test {
systemProperty "file.encoding", "utf-8"
useJUnitPlatform()
}
}

compileJava.options.encoding = 'UTF-8'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

эта штука обычно располагается выше блока с зависимостями. Это не критично, но меньше шанс, что потеряется


tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
3 changes: 2 additions & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#Tue Feb 11 23:22:06 MSK 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
65 changes: 0 additions & 65 deletions src/main/java/com/walking/lesson125_unit_testing/Main.java
Original file line number Diff line number Diff line change
@@ -1,77 +1,12 @@
package com.walking.lesson125_unit_testing;


import com.walking.lesson125_unit_testing.exception.RegexValidationException;
import com.walking.lesson125_unit_testing.model.FullName;

/**
* На базе вашего решения
* <a href="https://github.com/KFalcon2022/unit-testing-practical-task">задачи из урока 125</a>
* актуализируйте юнит-тесты с использованием Mockito. Сложность задачи напрямую зависит от качества декомпозиции в
* вашем предыдущем решении.
*/
public class Main {

public static final String FULL_NAME_REGEX = "^[А-Я][А-Яа-я-]* [А-Я][а-я]* [А-Я][а-я]+$";
public static final String DOUBLE_SURNAME_REGEX = "[А-Я][а-я]*-[А-Я][а-я]*";
public static final String NAME_REGEX = "[А-Я][а-я]*";
public static final String PATRONYMIC_REGEX = "[А-Я][а-я]+";

public static void main(String[] args) {
System.out.println(parseName("Иванов Иван Иванович"));
System.out.println(parseName("Иванов-Иванов Иван Иванович"));
System.out.println(parseName("Иванов-Иванов И Иванович"));
System.out.println(parseName("И-Иванов И Иванович"));
System.out.println(parseName("Иванов иван Иванович"));
// Все равно упадет на 30й строке.
// System.out.println(parseName("И-иванов И Иванович"));
// System.out.println(parseName("Иванов Иван иванович"));
// System.out.println(parseName("ИваНов Иван Иванович"));
// System.out.println(parseName("Ivanov Ivan"));
}

private static FullName parseName(String nameString) {
if (!nameString.matches(FULL_NAME_REGEX)) {
throw new RegexValidationException(nameString, FULL_NAME_REGEX);
}

FullName fullName = new FullName();
String[] splitNameString = nameString.split(" ");

String surname = splitNameString[0];
validateSurname(surname);
fullName.setSurname(surname);

String name = splitNameString[1];
validateName(name);
fullName.setName(name);

String patronymic = splitNameString[2];
validatePatronymic(patronymic);
fullName.setPatronymic(patronymic);

return fullName;
}

private static void validateSurname(String surname) {
if (surname.contains("-")) {
if (!surname.matches(DOUBLE_SURNAME_REGEX)) {
throw new RegexValidationException(surname, DOUBLE_SURNAME_REGEX);
}
} else {
validateName(surname);
}
}

private static void validateName(String name) {
if (!name.matches(NAME_REGEX)) {
throw new RegexValidationException(name, NAME_REGEX);
}
}

private static void validatePatronymic(String name) {
if (!name.matches(PATRONYMIC_REGEX)) {
throw new RegexValidationException(name, PATRONYMIC_REGEX);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.walking.lesson125_unit_testing.model;

import java.util.Objects;

public class FullName {
private String name;
private String surname;
Expand Down Expand Up @@ -42,4 +44,30 @@ public void setPatronymic(String patronymic) {
public String toString() {
return "%s %s %s".formatted(surname, name, patronymic);
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}

if (o == null || getClass() != o.getClass()) {
return false;
}

FullName fullName = (FullName) o;

return Objects.equals(name, fullName.name) && Objects.equals(surname, fullName.surname)
&& Objects.equals(patronymic, fullName.patronymic);
}

@Override
public int hashCode() {
int result = Objects.hashCode(name);

result = 31 * result + Objects.hashCode(surname);
result = 31 * result + Objects.hashCode(patronymic);

return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.walking.lesson125_unit_testing.service;

import com.walking.lesson125_unit_testing.model.FullName;

public class FullNameParsingService {
private final FullNameValidationService fullNameValidationService;

public FullNameParsingService(FullNameValidationService fullNameValidationService) {
this.fullNameValidationService = fullNameValidationService;
}

public FullName parseFullName(String nameString) {
if (nameString == null) {
throw new IllegalArgumentException("Unable parse null");
}

fullNameValidationService.validateFullName(nameString);

String[] splitNameString = nameString.split(" ");

String surname = splitNameString[0];
fullNameValidationService.validateSurname(surname);

String name = splitNameString[1];
fullNameValidationService.validateName(name);

String patronymic = splitNameString[2];
fullNameValidationService.validatePatronymic(patronymic);

return new FullName(name, surname, patronymic);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.walking.lesson125_unit_testing.service;

import com.walking.lesson125_unit_testing.exception.RegexValidationException;

public class FullNameValidationService {
private static final String FULL_NAME_REGEX = "^[А-Я][А-Яа-я-]* [А-Я][а-я]* [А-Я][а-я]+$";
private static final String DOUBLE_SURNAME_REGEX = "[А-Я][а-я]*-[А-Я][а-я]*";
private static final String NAME_REGEX = "[А-Я][а-я]*";
private static final String PATRONYMIC_REGEX = "[А-Я][а-я]+";

public void validateFullName(String nameString) {
if (!nameString.matches(FULL_NAME_REGEX)) {
throw new RegexValidationException(nameString, FULL_NAME_REGEX);
}
}

public void validateSurname(String surname) {
if (surname.contains("-")) {
if (!surname.matches(DOUBLE_SURNAME_REGEX)) {
throw new RegexValidationException(surname, DOUBLE_SURNAME_REGEX);
}
} else {
validateName(surname);
}
}

public void validateName(String name) {
if (!name.matches(NAME_REGEX)) {
throw new RegexValidationException(name, NAME_REGEX);
}
}

public void validatePatronymic(String name) {
if (!name.matches(PATRONYMIC_REGEX)) {
throw new RegexValidationException(name, PATRONYMIC_REGEX);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.walking.lesson125_unit_testing.service;

import com.walking.lesson125_unit_testing.exception.RegexValidationException;
import com.walking.lesson125_unit_testing.model.FullName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.function.Executable;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
class FullNameParsingServiceTest {
@InjectMocks
private FullNameParsingService fullNameParsingService;

@Mock
private FullNameValidationService fullNameValidationService;

@Test
void parseFullName_success() {
// given
FullName expected = new FullName("Иван", "Иванов", "Иванович");

// when
FullName result = fullNameParsingService.parseFullName("Иванов Иван Иванович");

// then
assertEquals(expected, result);

verify(fullNameValidationService).validateFullName(anyString());
verify(fullNameValidationService).validateSurname(anyString());
verify(fullNameValidationService).validateName(anyString());
verify(fullNameValidationService).validatePatronymic(anyString());
}

@Test
void parseFullName_failed_with_invalidFullName() {
// given
doThrow(RegexValidationException.class).when(fullNameValidationService)
.validateFullName(anyString());

// when
Executable actual = () -> fullNameParsingService.parseFullName(anyString());

// then
assertThrows(RegexValidationException.class, actual);

verify(fullNameValidationService).validateFullName(anyString());

verify(fullNameValidationService, never()).validateSurname(anyString());
verify(fullNameValidationService, never()).validateName(anyString());
verify(fullNameValidationService, never()).validatePatronymic(anyString());
}

@Test
void parseFullName_failed_with_null() {
// when
Executable actual = () -> fullNameParsingService.parseFullName(null);

// then
assertThrows(IllegalArgumentException.class, actual);

verify(fullNameValidationService, never()).validateFullName(anyString());
verify(fullNameValidationService, never()).validateSurname(anyString());
verify(fullNameValidationService, never()).validateName(anyString());
verify(fullNameValidationService, never()).validatePatronymic(anyString());
}
}
Loading