From 0c4c399fc894acf6ee3bd321f78bbd180b8b94d1 Mon Sep 17 00:00:00 2001 From: mitjaperko Date: Wed, 3 Nov 2021 20:11:29 +0100 Subject: [PATCH 1/3] Yea :) --- src/test/java/assertions/PersonTest.java | 38 ++++++++++++++++++------ 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/test/java/assertions/PersonTest.java b/src/test/java/assertions/PersonTest.java index ddfacc8..4df4eb2 100644 --- a/src/test/java/assertions/PersonTest.java +++ b/src/test/java/assertions/PersonTest.java @@ -1,8 +1,10 @@ package assertions; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.time.LocalDate; +import java.time.Period; class PersonTest { @@ -10,30 +12,48 @@ class PersonTest { @Test void getFullNameReturnsFirstnameSpaceLastname(){ - // TODO implement - throw new IllegalArgumentException("you should implement code here"); + Person p = new Person("Mitja", "Perko", null); + String fullName = p.getFullName(); + + Assertions.assertEquals(fullName, "Mitja Perko"); + Assertions.assertNotEquals(fullName, "Perko Mitja"); + + // + //throw new IllegalArgumentException("you should implement code here"); } - // TODO some more useful tests + // Other Test in the function on Top // --- getAge @Test void getAgeReturns10YearsIfBornIn2009() throws Exception { - // TODO verbessern. Hinweis: Repeatable (wiederholbar) zu jeder Zeit. - Person p = new Person("", "", LocalDate.of(2009, 1, 1)); - throw new IllegalArgumentException("you should implement code here"); + Person p = new Person("", "", LocalDate.now().minusYears(10)); + + Period age = p.getAge(); + + Assertions.assertEquals(10, age.getYears()); + + //throw new IllegalArgumentException("you should implement code here"); } @Test void getAgeReturns1DayIfYesterday() throws Exception { Person p = new Person("", "", LocalDate.now().minusDays(1)); + Period age = p.getAge(); - // TODO implement - throw new IllegalArgumentException("you should implement code here"); + Assertions.assertEquals(1, age.getDays()); + + //throw new IllegalArgumentException("you should implement code here"); } - // TODO some more useful tests + @Test + void getAgeReturns1MonthIfBornLastMonth() throws Exception { + Person p = new Person("", "", LocalDate.now().minusMonths(1)); + Period age = p.getAge(); + + Assertions.assertEquals(1, age.getMonths()); + } } From a631871972e027ecd2fc1edb9f4c761eb09ab122 Mon Sep 17 00:00:00 2001 From: mitjaperko Date: Wed, 17 Nov 2021 20:12:02 +0100 Subject: [PATCH 2/3] test --- src/test/java/fakes/UserControllerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/fakes/UserControllerTest.java b/src/test/java/fakes/UserControllerTest.java index 714b4c3..0194a15 100644 --- a/src/test/java/fakes/UserControllerTest.java +++ b/src/test/java/fakes/UserControllerTest.java @@ -25,7 +25,7 @@ void withValidInexistingUsername_returnsOK__NO_FAKE() { @Test void withValidInexistingUsername_returnsOK__FAKE() { // TODO - // 1. Test schneller machen + // 1. Test schneller machenrewtwertwert // 2. UserController.create so beinflussen, // dass einmal der "if"- und einmal der "else"-Fall durchlaufen wird } From 509f9a600adde67add5f1dc8d5b95f397f7c0006 Mon Sep 17 00:00:00 2001 From: mitjaperko Date: Wed, 17 Nov 2021 20:14:28 +0100 Subject: [PATCH 3/3] test --- src/main/java/fakes/FakeUserValidator.java | 23 +++ src/main/java/fakes/InjectDemo.java | 51 +++++++ src/main/java/fakes/UserController.java | 19 ++- src/main/java/fakes/UserValidator.java | 52 +++++-- src/main/java/fakes/mockDatabase.java | 17 +++ src/test/java/assertions/PersonTest.java | 38 ++--- src/test/java/fakes/UserControllerTest.java | 113 ++++++++++++--- src/test/java/fakes/UserValidatorTest.java | 148 +++++++++++++++++--- 8 files changed, 381 insertions(+), 80 deletions(-) create mode 100644 src/main/java/fakes/FakeUserValidator.java create mode 100644 src/main/java/fakes/InjectDemo.java create mode 100644 src/main/java/fakes/mockDatabase.java diff --git a/src/main/java/fakes/FakeUserValidator.java b/src/main/java/fakes/FakeUserValidator.java new file mode 100644 index 0000000..ff17563 --- /dev/null +++ b/src/main/java/fakes/FakeUserValidator.java @@ -0,0 +1,23 @@ +package fakes; + +public class FakeUserValidator extends UserValidator { + private boolean userExists; + + @Override + public boolean doesUsernameExist(String username) { + return this.userExists; + } + + public boolean doesUsernameExist(User usr, Database db) { + for(User user : db.getUsers()){ + if (user.getUsername().equals(usr.getUsername())){ + return true; + } + } + return false; + } + + public void setUserExists(boolean userExists) { + this.userExists = userExists; + } +} \ No newline at end of file diff --git a/src/main/java/fakes/InjectDemo.java b/src/main/java/fakes/InjectDemo.java new file mode 100644 index 0000000..326fdd2 --- /dev/null +++ b/src/main/java/fakes/InjectDemo.java @@ -0,0 +1,51 @@ +package fakes; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +interface CanLog { + void log(String message); +} + +class FileLogger implements CanLog { + @Override + public void log(String message) { + try { + Files.write(Paths.get("src/main/resources/log.txt"), message.getBytes(StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} + +class ConsoleLogger implements CanLog { + @Override + public void log(String message) { + System.out.println("LOG: " + message); + } +} + +class Logger { + private final CanLog canLog; + + public Logger(CanLog canLog) { + this.canLog = canLog; + } + + public void doLog(String message) { + canLog.log(message); + } +} + +public class InjectDemo { + + public static void main(String[] args) { + final Logger logger = new Logger(new FileLogger()); + logger.doLog("test log 1"); + + final Logger logger2 = new Logger(new ConsoleLogger()); + logger2.doLog("test log 2"); + } +} diff --git a/src/main/java/fakes/UserController.java b/src/main/java/fakes/UserController.java index d61b7e8..e969044 100644 --- a/src/main/java/fakes/UserController.java +++ b/src/main/java/fakes/UserController.java @@ -1,20 +1,29 @@ + package fakes; public class UserController { - private static Database db = FileDatabase.getInstance(); + private final Database db; + private final UserValidator uv; + + public UserController(UserValidator uv, Database db) { + this.uv = uv; + this.db = db; + } public Message create(User user){ if(user == null){ throw new IllegalArgumentException("user required"); } - Boolean canCreate = UserValidator.isValidUsername(user.getUsername()) - && !UserValidator.doesUsernameExist(user.getUsername()); + Boolean canCreate = this.uv.isValidUsername(user.getUsername()) + && !this.uv.doesUsernameExist(user.getUsername()); if(canCreate){ - db.addUser(user); + this.db.addUser(user); return Message.createOK(); }else{ return Message.createNotOK(); } } -} + + +} \ No newline at end of file diff --git a/src/main/java/fakes/UserValidator.java b/src/main/java/fakes/UserValidator.java index 0bd28b2..2dfe4a7 100644 --- a/src/main/java/fakes/UserValidator.java +++ b/src/main/java/fakes/UserValidator.java @@ -1,18 +1,25 @@ package fakes; -public class UserValidator { +import java.util.Locale; - private static Database db = FileDatabase.getInstance(); +public class UserValidator { + private static Database db; - public static boolean doesUsernameExist(String username){ - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } + public UserValidator() { + this.db = FileDatabase.getInstance(); + } + public UserValidator(Database db) { + this.db = db; + } + public boolean doesUsernameExist(String username){ +// try { +// Thread.sleep(5000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } for(User user : db.getUsers()){ - if (user.getUsername().equals(username)){ + if (user.getUsername().toLowerCase(Locale.ROOT).equals(username.toLowerCase(Locale.ROOT))){ return true; } } @@ -20,6 +27,29 @@ public static boolean doesUsernameExist(String username){ } public static boolean isValidUsername(String username){ - return true; + boolean result = true; + + // usernameContainsNumberButNotAsFirstChar + // starte mit i=1 damit der index 0 nicht beruecksichtigt wird + for(int i = 1; i < username.length(); i++) { + char testChar = username.charAt(i); + if(Character.isDigit(testChar)) { + return true; + } + } + + char[] chars = username.toCharArray(); + for(char c : chars) { + // usernameOnlyLetters + if(!Character.isLetter(c)) { + result = false; + } + // usernameContainsAnyNonAlphaNumericChar + if(!Character.isLetterOrDigit(c)) { + result = false; + } + } + return result; } -} + +} \ No newline at end of file diff --git a/src/main/java/fakes/mockDatabase.java b/src/main/java/fakes/mockDatabase.java new file mode 100644 index 0000000..592b500 --- /dev/null +++ b/src/main/java/fakes/mockDatabase.java @@ -0,0 +1,17 @@ +package fakes; + +import java.util.ArrayList; +import java.util.List; + +public class mockDatabase extends Database { + List users = new ArrayList<>(); + @Override + public void addUser(User user) { + users.add(user); + } + + @Override + public List getUsers() { + return users; + } +} \ No newline at end of file diff --git a/src/test/java/assertions/PersonTest.java b/src/test/java/assertions/PersonTest.java index 4df4eb2..ddfacc8 100644 --- a/src/test/java/assertions/PersonTest.java +++ b/src/test/java/assertions/PersonTest.java @@ -1,10 +1,8 @@ package assertions; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.time.LocalDate; -import java.time.Period; class PersonTest { @@ -12,48 +10,30 @@ class PersonTest { @Test void getFullNameReturnsFirstnameSpaceLastname(){ - Person p = new Person("Mitja", "Perko", null); - String fullName = p.getFullName(); - - Assertions.assertEquals(fullName, "Mitja Perko"); - Assertions.assertNotEquals(fullName, "Perko Mitja"); - - // - //throw new IllegalArgumentException("you should implement code here"); + // TODO implement + throw new IllegalArgumentException("you should implement code here"); } - // Other Test in the function on Top + // TODO some more useful tests // --- getAge @Test void getAgeReturns10YearsIfBornIn2009() throws Exception { + // TODO verbessern. Hinweis: Repeatable (wiederholbar) zu jeder Zeit. + Person p = new Person("", "", LocalDate.of(2009, 1, 1)); - Person p = new Person("", "", LocalDate.now().minusYears(10)); - - Period age = p.getAge(); - - Assertions.assertEquals(10, age.getYears()); - - //throw new IllegalArgumentException("you should implement code here"); + throw new IllegalArgumentException("you should implement code here"); } @Test void getAgeReturns1DayIfYesterday() throws Exception { Person p = new Person("", "", LocalDate.now().minusDays(1)); - Period age = p.getAge(); - Assertions.assertEquals(1, age.getDays()); - - //throw new IllegalArgumentException("you should implement code here"); + // TODO implement + throw new IllegalArgumentException("you should implement code here"); } - @Test - void getAgeReturns1MonthIfBornLastMonth() throws Exception { - Person p = new Person("", "", LocalDate.now().minusMonths(1)); - Period age = p.getAge(); - - Assertions.assertEquals(1, age.getMonths()); - } + // TODO some more useful tests } diff --git a/src/test/java/fakes/UserControllerTest.java b/src/test/java/fakes/UserControllerTest.java index 0194a15..47da755 100644 --- a/src/test/java/fakes/UserControllerTest.java +++ b/src/test/java/fakes/UserControllerTest.java @@ -4,6 +4,13 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import javax.xml.crypto.Data; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.times; + class UserControllerTest { // Pro getestete Methode gibt es eine inner class (Hier für UserController.create) @@ -13,44 +20,112 @@ class create { // --- Testing with Fakes --- @Test - void withValidInexistingUsername_returnsOK__NO_FAKE() { - UserController ctrl = new UserController(); + @org.junit.jupiter.api.Disabled + void withValidInexistingUsername_returnsOK__NO_FAKE_DEMO() { + // Arrange + UserController ctrl = new UserController(new UserValidator(), FileDatabase.getInstance()); User user = new User("kalua"); + // Act Message result = ctrl.create(user); + // Assert Assertions.assertEquals(result.status, Message.Status.OK); } @Test - void withValidInexistingUsername_returnsOK__FAKE() { - // TODO - // 1. Test schneller machenrewtwertwert - // 2. UserController.create so beinflussen, + void withValidInexistentUsername_returnsOK__FAKE() { + // 1. Test schneller machen + // 2. UserController.create so beeinflussen, // dass einmal der "if"- und einmal der "else"-Fall durchlaufen wird + + // Tipp: Welche Methode sorgt dafür, dass canCreate im UserController true bzw. false ist? + // Kannst du deren Rückgabetyp beeinflussen? + + // Die Schritte die du ausprogrammieren musst: + // 1. Arrange: UserController mit allen Abhängigkeiten initialisieren + // 2. Act: UserController.create Methode aufrufen + // 3. Assert: Rückgabewert von UserController.create prüfen + + // -> implement test + /* Arrange */ + FakeUserValidator uv = new FakeUserValidator(); + UserController uc = new UserController(uv, new mockDatabase()); + User user = new User("kalua"); + /* Act */ + Message result = uc.create(user); + /* Assert */ + Assertions.assertEquals(result.status, Message.Status.OK); } @Test - void withValidInexistingUsername_returnsOK__MOCKITO() { - // TODO + void withValidInexistentUsername_returnsOK__MOCKITO() { + // -> implement test + /* ARRANGE */ + UserValidator uv = mock(UserValidator.class); + FileDatabase db = mock(FileDatabase.class); + UserController uc = new UserController(uv, db); + User user = new User("kalua"); + /* ACT */ + Message result = uc.create(user); + /* ASSERT */ + Assertions.assertEquals(result.status, Message.Status.OK); } @Test - void withValidInexitingUserName_addUserToDB__FAKE() { - // TODO + void withValidInexistentUsername_shouldAddUserToDB__FAKE() { + // Der Test soll prüfen, ob der Benutzer tatsächlich der DB hinzugefügt wurde. + // Dazu soll ein Mock-Objekt für die Database Klasse verwendet werden. + + // -> implement test + // Tipp: Wie kann dein Test feststellen, ob der UserController der Datenbank einen Benutzer hinzugefügt hat? + // Welche Art von Fake (Stub oder Mock) kann dir weiterhelfen? + /* ARRANGE */ + FakeUserValidator uv = new FakeUserValidator(); + uv.setUserExists(false); + mockDatabase db = new mockDatabase(); + UserController uc = new UserController(uv, db); + User user = new User("kalua"); + /* ACT */ + Message result = uc.create(user); + boolean result2 = uv.doesUsernameExist(user, db); + /* ASSERT */ + Assertions.assertEquals(result.status, Message.Status.OK); + Assertions.assertTrue(result2); } @Test - void withValidInexitingUserName_addUserToDB__MOCKITO() { - // TODO + void withValidInexistentUsername_shouldAddUserToDB__MOCKITO() { + // Der Test soll prüfen, ob der Benutzer tatsächlich der DB hinzugefügt wurde. + // Dazu soll ein Mock-Objekt für die Database Klasse verwendet werden. + + // Tipp: Du kannst prüfen, ob der User hinzugefügt wurde, + // indem du prüfst wie of die Methode Database.addUser aufgerufen wurde. + // -> implement test + /* ARRANGE */ + UserValidator uv = mock(UserValidator.class); + FileDatabase db = mock(FileDatabase.class); + UserController uc = new UserController(uv, db); + User user = new User("kalua"); + + doReturn(true).when(uv).isValidUsername(anyString()); + // eigentlich müsste untenstehende anweisung rein, ergibt jedoch einen error... keine ahnung wieso. + //doReturn(true).when(uv).doesUsernameExist(anyString()); + + /* ACT */ + Message result = uc.create(user); + verify(db, times(1)).addUser(any()); + + /* ASSERT */ + Assertions.assertEquals(result.status, Message.Status.OK); } // --- Testing Exceptions --- @Test - void TRY_CATCH_withNullUser_throwsIllegalArgumentExc() { + void withNullUser_throwsIllegalArgumentExc__TRY_CATCH() { try { - UserController ctrl = new UserController(); + UserController ctrl = new UserController(new UserValidator(), FileDatabase.getInstance()); ctrl.create(null); Assertions.fail("No IllegalArgumentException was thrown"); } catch (IllegalArgumentException ex) { @@ -60,20 +135,20 @@ void TRY_CATCH_withNullUser_throwsIllegalArgumentExc() { } @Test - void THROWN_withNullUser_throwsIllegalArgumentException() { + void withNullUser_throwsIllegalArgumentException__THROWN() { Assertions.assertThrows(IllegalArgumentException.class, () -> { - UserController ctrl = new UserController(); + UserController ctrl = new UserController(new UserValidator(), FileDatabase.getInstance()); ctrl.create(null); }); } @Test - void THROWN_MESSAGE_withNullUser_throwsIllegalArgumentExceptionWithMessage() { + void withNullUser_throwsIllegalArgumentExceptionWithMessage__THROWN_MESSAGE() { Exception thrown = Assertions.assertThrows(IllegalArgumentException.class, () -> { - UserController ctrl = new UserController(); + UserController ctrl = new UserController(new UserValidator(), FileDatabase.getInstance()); ctrl.create(null); }); Assertions.assertTrue(thrown.getMessage().contains("required")); } } -} +} \ No newline at end of file diff --git a/src/test/java/fakes/UserValidatorTest.java b/src/test/java/fakes/UserValidatorTest.java index 4cffc57..03a6d04 100644 --- a/src/test/java/fakes/UserValidatorTest.java +++ b/src/test/java/fakes/UserValidatorTest.java @@ -1,49 +1,165 @@ package fakes; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.times; + class UserValidatorTest { + /** + * Alle Tests in der folgenden Klasse isValidUsername sollen die Methode UserValidator.isValidUsername testen. + * Damit alle Tests grün werden, musst du die Implementation von UserValidator.isValidUsername anpassen! + */ @Nested - class isValidUsername{ + class isValidUsername { @Test - void returnsTrueIfOnlyLetters(){ - throw new IllegalArgumentException("you should implement code here"); + void returnsTrueIfOnlyLetters() { + /* ARRANGE */ + UserValidator uv = new UserValidator(); + User user = new User("kalua"); + + /* ACT */ + // -> Testcode anpassen, damit er das testet was der Testname sagt. + boolean result = uv.isValidUsername(user.getUsername()); + + /* ASSERT */ + Assertions.assertTrue(result); } @Test void returnsFalseIfStartsWithNumber(){ - throw new IllegalArgumentException("you should implement code here"); + // -> implement test + /* ARRANGE */ + UserValidator uv = new UserValidator(); + User user = new User("1kalua"); + + /* ACT */ + boolean result = uv.isValidUsername(user.getUsername()); + + /* ASSERT */ + Assertions.assertFalse(result); } @Test - void returnsTrueIfContainsNumberButNotAsFirstChar(){ - throw new IllegalArgumentException("you should implement code here"); + void returnsTrueIfContainsNumberButNotAsFirstChar() { + // -> implement test + /* ARRANGE */ + UserValidator uv = new UserValidator(); + User user = new User("kalua1"); + + /* ACT */ + boolean result = uv.isValidUsername(user.getUsername()); + + /* ASSERT */ + Assertions.assertTrue(result); } @Test - void returnsFalseIfContainsAnyNonAlphanumericChar(){ - throw new IllegalArgumentException("you should implement code here"); + void returnsFalseIfContainsAnyNonAlphanumericChar() { + // -> implement test + /* ARRANGE */ + UserValidator uv = new UserValidator(); + User user = new User("kal_ua"); + + /* ACT */ + boolean result = uv.isValidUsername(user.getUsername()); + + /* ASSERT */ + Assertions.assertFalse(result); } } - static class doesUsernameExist{ + /** + * Alle Tests in der folgenden Klasse doesUsernameExist sollen die Methode UserValidator.doesUsernameExist testen. + * Damit alle Tests grün werden, musst du die Implementation von UserValidator.doesUsernameExist anpassen! + */ + static class doesUsernameExist { + @Test + void returnsFalseIfUsernameNotInDBYet__FAKE() { + // -> implementiere / ergänze den Test hier, so dass dieser kompiliert und grün ist. + /* ARRANGE */ + FakeUserValidator uv = new FakeUserValidator(); + uv.setUserExists(false); + + /* ACT */ + boolean usernameExist = uv.doesUsernameExist("peter"); + + /* ASSERT */ + Assertions.assertFalse(usernameExist); + } @Test - void returnsFalseIfUsernameNotInDBYet(){ - throw new IllegalArgumentException("you should implement code here"); + void returnsFalseIfUsernameNotInDBYet__MOCKITO() { + // -> implement test + /* ARRANGE */ + UserValidator uv = mock(UserValidator.class); + doReturn(false).when(uv).doesUsernameExist(anyString()); + + /* ACT */ + boolean usernameNotInDb = uv.doesUsernameExist("peter"); + verify(uv, times(1)).doesUsernameExist(anyString()); + + /* ASSERT */ + Assertions.assertFalse(usernameNotInDb); } @Test - void returnsTrueIfUsernameInDB(){ - throw new IllegalArgumentException("you should implement code here"); + void returnsTrueIfUsernameInDB__FAKE() { + // -> implementiere / ergänze den Test hier, so dass dieser kompiliert und grün ist. + /* ARRANGE */ + FakeUserValidator uv = new FakeUserValidator(); + uv.setUserExists(true); + + /* ACT */ + boolean usernameExist = uv.doesUsernameExist("peter"); + + /* ASSERT */ + Assertions.assertTrue(usernameExist); } @Test - void returnsTrueIfSameNameInDBButWithDifferentLetterCasing(){ - throw new IllegalArgumentException("you should implement code here"); + void returnsTrueIfUsernameInDB__MOCKITO() { + // -> implement test + /* ARRANGE */ + FileDatabase db = mock(FileDatabase.class); + User user = new User("peter"); + + // mock-db soll user zurueckgeben, wenn danach gefragt wird + List users = db.getUsers(); + users.add(user); + doReturn(users).when(db).getUsers(); + + // uservalidator nutzt die mockte db + UserValidator uv = new UserValidator(db); + + /* ACT */ + boolean usernameInDb = uv.doesUsernameExist(user.getUsername()); + System.out.println(usernameInDb); + + /* ASSERT */ + Assertions.assertTrue(usernameInDb); + } + + @Test + void returnsTrueIfSameNameInDBButWithDifferentLetterCasing() { + // -> implement test + /* ARRANGE */ + UserValidator uv = new UserValidator(); + User user = new User("kAlUa"); + + /* ACT */ + boolean result = uv.doesUsernameExist(user.getUsername()); + + /* ASSERT */ + Assertions.assertTrue(result); } } -} +} \ No newline at end of file