diff --git a/unitofwork/pom.xml b/unitofwork/pom.xml index e790c8168..38b0e1b42 100644 --- a/unitofwork/pom.xml +++ b/unitofwork/pom.xml @@ -10,6 +10,16 @@ 4.0.0 unit-of-work + + + junit + junit + + + org.mockito + mockito-core + + \ No newline at end of file diff --git a/unitofwork/src/main/java/com/iluwatar/unitofwork/IUnitOfWork.java b/unitofwork/src/main/java/com/iluwatar/unitofwork/IUnitOfWork.java index 9fb2e362b..d63a6d8c7 100644 --- a/unitofwork/src/main/java/com/iluwatar/unitofwork/IUnitOfWork.java +++ b/unitofwork/src/main/java/com/iluwatar/unitofwork/IUnitOfWork.java @@ -28,12 +28,16 @@ package com.iluwatar.unitofwork; * @param Any generic entity */ public interface IUnitOfWork { - public void registerNew(T entity); + String INSERT = "INSERT"; + String DELETE = "DELETE"; + String MODIFY = "MODIFY"; - public void registerModified(T entity); + void registerNew(T entity); - public void registerDeleted(T entity); + void registerModified(T entity); - public void commit(); + void registerDeleted(T entity); + + void commit(); } \ No newline at end of file diff --git a/unitofwork/src/main/java/com/iluwatar/unitofwork/Student.java b/unitofwork/src/main/java/com/iluwatar/unitofwork/Student.java index fa80089f2..9b77717ec 100644 --- a/unitofwork/src/main/java/com/iluwatar/unitofwork/Student.java +++ b/unitofwork/src/main/java/com/iluwatar/unitofwork/Student.java @@ -42,5 +42,5 @@ public class Student { this.name = name; this.address = address; } - + } diff --git a/unitofwork/src/main/java/com/iluwatar/unitofwork/StudentDatabase.java b/unitofwork/src/main/java/com/iluwatar/unitofwork/StudentDatabase.java new file mode 100644 index 000000000..678fe4026 --- /dev/null +++ b/unitofwork/src/main/java/com/iluwatar/unitofwork/StudentDatabase.java @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017 Piyush Chaudhari + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.iluwatar.unitofwork; + +/** + * Act as Database for student records. + */ +public class StudentDatabase { + + public void insert(Student student) { + //Some insert logic to DB + } + + public void modify(Student student) { + //Some modify logic to DB + } + + public void delete(Student student) { + //Some delete logic to DB + } +} diff --git a/unitofwork/src/main/java/com/iluwatar/unitofwork/StudentRepository.java b/unitofwork/src/main/java/com/iluwatar/unitofwork/StudentRepository.java new file mode 100644 index 000000000..a2cff4ada --- /dev/null +++ b/unitofwork/src/main/java/com/iluwatar/unitofwork/StudentRepository.java @@ -0,0 +1,110 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017 Piyush Chaudhari + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.iluwatar.unitofwork; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * {@link StudentRepository} Student database repository. + * supports unit of work for student data. + */ +public class StudentRepository implements IUnitOfWork { + private Map> context; + private StudentDatabase studentDatabase; + + /** + * @param context set of operations to be perform during commit. + * @param studentDatabase Database for student records. + */ + public StudentRepository(Map> context, StudentDatabase studentDatabase) { + this.context = context; + this.studentDatabase = studentDatabase; + } + + @Override + public void registerNew(Student student) { + register(student, IUnitOfWork.INSERT); + } + + @Override + public void registerModified(Student student) { + register(student, IUnitOfWork.MODIFY); + + } + + @Override + public void registerDeleted(Student student) { + register(student, IUnitOfWork.DELETE); + } + + private void register(Student student, String operation) { + List studentsToOperate = context.get(operation); + if (studentsToOperate == null) { + studentsToOperate = new ArrayList<>(); + } + studentsToOperate.add(student); + context.put(operation, studentsToOperate); + } + + @Override + public void commit() { + if (context == null || context.size() == 0) { + return; + } + if (context.containsKey(IUnitOfWork.INSERT)) { + commitInsert(); + } + + if (context.containsKey(IUnitOfWork.MODIFY)) { + commitModify(); + } + if (context.containsKey(IUnitOfWork.DELETE)) { + commitDelete(); + } + } + + private void commitDelete() { + List deletedStudents = context.get(IUnitOfWork.DELETE); + for (Student student : deletedStudents) { + studentDatabase.delete(student); + } + } + + private void commitModify() { + List modifiedStudents = context.get(IUnitOfWork.MODIFY); + for (Student student : modifiedStudents) { + studentDatabase.modify(student); + } + } + + private void commitInsert() { + List studentsToBeInserted = context.get(IUnitOfWork.INSERT); + for (Student student : studentsToBeInserted) { + studentDatabase.insert(student); + } + } +} diff --git a/unitofwork/src/test/java/com/iluwatar/unitofwork/StudentRepositoryTest.java b/unitofwork/src/test/java/com/iluwatar/unitofwork/StudentRepositoryTest.java new file mode 100644 index 000000000..9a71dcbbc --- /dev/null +++ b/unitofwork/src/test/java/com/iluwatar/unitofwork/StudentRepositoryTest.java @@ -0,0 +1,147 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2017 Piyush Chaudhari + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.iluwatar.unitofwork; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; + +/** + * tests {@link StudentRepository} + */ +@RunWith(MockitoJUnitRunner.class) +public class StudentRepositoryTest { + private final Student student1 = new Student(1, "Ram", "street 9, cupertino"); + private final Student student2 = new Student(1, "Sham", "Z bridge, pune"); + + private Map> context; + @Mock + private StudentDatabase studentDatabase; + private StudentRepository studentRepository; + + @Before + public void setUp() throws Exception { + context = new HashMap<>(); + studentRepository = new StudentRepository(context, studentDatabase); + } + + @Test + public void shouldSaveNewStudentWithoutWritingToDb() throws Exception { + studentRepository.registerNew(student1); + studentRepository.registerNew(student2); + + assertEquals(2, context.get(IUnitOfWork.INSERT).size()); + verifyNoMoreInteractions(studentDatabase); + } + + @Test + public void shouldSaveDeletedStudentWithoutWritingToDb() throws Exception { + studentRepository.registerDeleted(student1); + studentRepository.registerDeleted(student2); + + assertEquals(2, context.get(IUnitOfWork.DELETE).size()); + verifyNoMoreInteractions(studentDatabase); + } + + @Test + public void shouldSaveModifiedStudentWithoutWritingToDb() throws Exception { + studentRepository.registerModified(student1); + studentRepository.registerModified(student2); + + assertEquals(2, context.get(IUnitOfWork.MODIFY).size()); + verifyNoMoreInteractions(studentDatabase); + } + + @Test + public void shouldSaveAllLocalChangesToDb() throws Exception { + context.put(IUnitOfWork.INSERT, Collections.singletonList(student1)); + context.put(IUnitOfWork.MODIFY, Collections.singletonList(student1)); + context.put(IUnitOfWork.DELETE, Collections.singletonList(student1)); + + studentRepository.commit(); + + verify(studentDatabase, times(1)).insert(student1); + verify(studentDatabase, times(1)).modify(student1); + verify(studentDatabase, times(1)).delete(student1); + } + + @Test + public void shouldNotWriteToDbIfContextIsNull() throws Exception { + StudentRepository studentRepository = new StudentRepository(null, studentDatabase); + + studentRepository.commit(); + + verifyNoMoreInteractions(studentDatabase); + } + + @Test + public void shouldNotWriteToDbIfNothingToCommit() throws Exception { + StudentRepository studentRepository = new StudentRepository(new HashMap<>(), studentDatabase); + + studentRepository.commit(); + + verifyZeroInteractions(studentDatabase); + } + + @Test + public void shouldNotInsertToDbIfNoRegisteredStudentsToBeCommitted() throws Exception { + context.put(IUnitOfWork.MODIFY, Collections.singletonList(student1)); + context.put(IUnitOfWork.DELETE, Collections.singletonList(student1)); + + studentRepository.commit(); + + verify(studentDatabase, never()).insert(student1); + } + + @Test + public void shouldNotModifyToDbIfNotRegisteredStudentsToBeCommitted() throws Exception { + context.put(IUnitOfWork.INSERT, Collections.singletonList(student1)); + context.put(IUnitOfWork.DELETE, Collections.singletonList(student1)); + + studentRepository.commit(); + + verify(studentDatabase, never()).modify(student1); + } + + @Test + public void shouldNotDeleteFromDbIfNotRegisteredStudentsToBeCommitted() throws Exception { + context.put(IUnitOfWork.INSERT, Collections.singletonList(student1)); + context.put(IUnitOfWork.MODIFY, Collections.singletonList(student1)); + + studentRepository.commit(); + + verify(studentDatabase, never()).delete(student1); + } +} \ No newline at end of file