Repository: iluwatar/java-design-patterns
Issue: Template Method
Labels: type: enhancement
info: good first issue
epic: design

As statet in the referenced tutorial [Template-method Pattern Tutorial](https://www.journaldev.com/1763/template-method-design-pattern-in-java)
I would add a note in the pattern description that the template method should be declared `final`. 

> To make sure that subclasses don’t override the template method, we should make it final.

And I would change the code accordingly.


Issue comments:
Yes, I agree with you.
That‘s right.
@iluwatar can you please assign this to me?
@iluwatar @dgruntz 
where would you want to put this new comment?
`To make sure that subclasses don’t override the template method, we should make it final.`
I do not want to add this comment but rather change the code and make the template method final. This change has already been made with PR #1100, but as long as this PR is open this issue remains open as well; and the PR can't be merged yet as there is a [issue](https://github.com/mockito/mockito/issues/1826) in Mockito which has not yet been fixed.
@elouie-code it's assigned to you now
@elouie-code is there any update regarding this issue or any progress that you made?
hi @ohbus , @iluwatar , looks like nothing happens here, can I do a PR for this ticket?
The PR #1100 is already open, but the PR can't be merged yet as there is a [issue](https://github.com/mockito/mockito/issues/1826) in Mockito which has not yet been fixed. I just checked whether the problem has been fixed with version 3.12.4 of Mockito, but this is not the case.
I see, but in the PR #1100 there is no adjustment of README documentation (explanation why template method should be marked "final" and changing the sample code). 
Agreed, this could be added, and probably the class diagram needs to be adjusted as well (I don't know whether final methods are specially marked, in UML I would use a <<final>> stereotype).
ok, so assign this ticket to me if you want to have the adjustment of the documentation:
* explanation why final is important in the Template Pattern
* adjustment of all code snippets
* adjustment of the class diagram

@dgruntz to be honest I wouldn't wait with your change until mockito fixes the issue with final methods. I would merge the code (without unit test) and create a reminder ticket for future to create a unit test with mockito so you are not blocked with the change in the sample. What do you think about it?
@syfds We could do that. We can merge the code without the unit tests which would drop code coverage and is not a good thing to do, though these are not production codes.

We can wait for @iluwatar's suggestion on this. What do you suggest @dgruntz?
What @syfds suggested sounds reasonable to me
I will take over and submit a new pull request.
Hello, @iluwatar, I would like to work on this please assign this issue to me
All right, good luck @shibicr93 
Fixed with PR #2057
@iluwatar  please assign this to @dgruntz  since he has already fixed it
Let's keep the issue open until the PR has been merged

Pull request review comments:

Patch that resolved the issue:
diff --git a/template-method/README.md b/template-method/README.md
index 7209176f2255..ba34441e0ca8 100644
--- a/template-method/README.md
+++ b/template-method/README.md
@@ -39,6 +39,10 @@ Wikipedia says
 **Programmatic Example**
 
 Let's first introduce the template method class along with its concrete implementations.
+To make sure that subclasses don’t override the template method, the template method (in our case
+method `steal`) should be declared `final`, otherwise the skeleton defined in the base class could
+be overridden in subclasses.
+
 
 ```java
 @Slf4j
@@ -50,7 +54,7 @@ public abstract class StealingMethod {
 
   protected abstract void stealTheItem(String target);
 
-  public void steal() {
+  public final void steal() {
     var target = pickTarget();
     LOGGER.info("The target has been chosen as {}.", target);
     confuseTarget(target);
diff --git a/template-method/pom.xml b/template-method/pom.xml
index ec791eae4c55..dc75fdef0212 100644
--- a/template-method/pom.xml
+++ b/template-method/pom.xml
@@ -41,7 +41,7 @@
     </dependency>
     <dependency>
       <groupId>org.mockito</groupId>
-      <artifactId>mockito-core</artifactId>
+      <artifactId>mockito-inline</artifactId>
       <scope>test</scope>
     </dependency>
   </dependencies>
diff --git a/template-method/src/main/java/com/iluwatar/templatemethod/StealingMethod.java b/template-method/src/main/java/com/iluwatar/templatemethod/StealingMethod.java
index ea4248548db2..db8813fa2bb9 100644
--- a/template-method/src/main/java/com/iluwatar/templatemethod/StealingMethod.java
+++ b/template-method/src/main/java/com/iluwatar/templatemethod/StealingMethod.java
@@ -41,7 +41,7 @@ public abstract class StealingMethod {
   /**
    * Steal.
    */
-  public void steal() {
+  public final void steal() {
     var target = pickTarget();
     LOGGER.info("The target has been chosen as {}.", target);
     confuseTarget(target);


Test patch:
diff --git a/template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java b/template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java
index eaf7699acffd..9f802597394e 100644
--- a/template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java
+++ b/template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java
@@ -24,7 +24,7 @@
  */
 package com.iluwatar.templatemethod;
 
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
@@ -42,11 +42,14 @@ public class HalflingThiefTest {
    */
   @Test
   void testSteal() {
-    final var method = mock(StealingMethod.class);
+    final var method = spy(StealingMethod.class);
     final var thief = new HalflingThief(method);
 
     thief.steal();
     verify(method).steal();
+    String target = verify(method).pickTarget();
+    verify(method).confuseTarget(target);
+    verify(method).stealTheItem(target);
 
     verifyNoMoreInteractions(method);
   }
@@ -56,19 +59,23 @@ void testSteal() {
    */
   @Test
   void testChangeMethod() {
-    final var initialMethod = mock(StealingMethod.class);
+    final var initialMethod = spy(StealingMethod.class);
     final var thief = new HalflingThief(initialMethod);
 
     thief.steal();
     verify(initialMethod).steal();
+    String target = verify(initialMethod).pickTarget();
+    verify(initialMethod).confuseTarget(target);
+    verify(initialMethod).stealTheItem(target);
 
-    final var newMethod = mock(StealingMethod.class);
+    final var newMethod = spy(StealingMethod.class);
     thief.changeMethod(newMethod);
 
     thief.steal();
     verify(newMethod).steal();
-
+    String newTarget = verify(newMethod).pickTarget();
+    verify(newMethod).confuseTarget(newTarget);
+    verify(newMethod).stealTheItem(newTarget);
     verifyNoMoreInteractions(initialMethod, newMethod);
-
   }
 }
\ No newline at end of file