Repository: mockito/mockito
Issue: Add AtMostOnce(),rename one testClass and one TODO.

Hi,

I would like to make a quick contribution on this project.

I add atMostOnce(), it seem's not to be a big feature. I just want to highlight the fact you have the function atLeastOnce() but nothing for the atMostOnce case. 

I rename the testClass ThreadVerifiesContinuoslyInteractingMockTest on ThreadVerifiesContinuouslyInteractingMockTest and the TODO on toString() from HamcrestArgumentMatcher<T>.



Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/java/org/mockito/Mockito.java b/src/main/java/org/mockito/Mockito.java
index 5066eec3d7..ec710a66a5 100644
--- a/src/main/java/org/mockito/Mockito.java
+++ b/src/main/java/org/mockito/Mockito.java
@@ -320,6 +320,7 @@
  * verify(mockedList, never()).add("never happened");
  *
  * //verification using atLeast()/atMost()
+ * verify(mockedList, atMostOnce()).add("once");
  * verify(mockedList, atLeastOnce()).add("three times");
  * verify(mockedList, atLeast(2)).add("three times");
  * verify(mockedList, atMost(5)).add("three times");
@@ -2724,6 +2725,22 @@ public static VerificationMode atLeast(int minNumberOfInvocations) {
         return VerificationModeFactory.atLeast(minNumberOfInvocations);
     }
 
+    /**
+     * Allows at-most-once verification. E.g:
+     * <pre class="code"><code class="java">
+     *   verify(mock, atMostOnce()).someMethod("some arg");
+     * </code></pre>
+     * Alias to <code>atMost(1)</code>.
+     * <p>
+     * See examples in javadoc for {@link Mockito} class
+     *
+     * @return verification mode
+     */
+    @CheckReturnValue
+    public static VerificationMode atMostOnce() {
+        return VerificationModeFactory.atMostOnce();
+    }
+
     /**
      * Allows at-most-x verification. E.g:
      * <pre class="code"><code class="java">
diff --git a/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java b/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java
index 9892422e77..5183136ae7 100644
--- a/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java
+++ b/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java
@@ -26,7 +26,7 @@ public boolean isVarargMatcher() {
     }
 
     public String toString() {
-        //TODO SF add unit tests and integ test coverage for describeTo()
+        //TODO SF add unit tests and integ test coverage for toString()
         return StringDescription.toString(matcher);
     }
 }
diff --git a/src/main/java/org/mockito/internal/verification/VerificationModeFactory.java b/src/main/java/org/mockito/internal/verification/VerificationModeFactory.java
index 1f8e8b6c25..b7c882daf6 100644
--- a/src/main/java/org/mockito/internal/verification/VerificationModeFactory.java
+++ b/src/main/java/org/mockito/internal/verification/VerificationModeFactory.java
@@ -33,6 +33,10 @@ public static NoMoreInteractions noMoreInteractions() {
         return new NoMoreInteractions();
     }
 
+    public static VerificationMode atMostOnce() {
+        return atMost(1);
+    }
+
     public static VerificationMode atMost(int maxNumberOfInvocations) {
         return new AtMost(maxNumberOfInvocations);
     }
diff --git a/src/main/java/org/mockito/internal/verification/VerificationWrapper.java b/src/main/java/org/mockito/internal/verification/VerificationWrapper.java
index b471342cf9..66336a94f1 100644
--- a/src/main/java/org/mockito/internal/verification/VerificationWrapper.java
+++ b/src/main/java/org/mockito/internal/verification/VerificationWrapper.java
@@ -37,6 +37,10 @@ public VerificationMode atLeast(int minNumberOfInvocations) {
         return copySelfWithNewVerificationMode(VerificationModeFactory.atLeast(minNumberOfInvocations));
     }
 
+    public VerificationMode atMostOnce() {
+        return copySelfWithNewVerificationMode(VerificationModeFactory.atMostOnce());
+    }
+
     public VerificationMode atMost(int maxNumberOfInvocations) {
         return copySelfWithNewVerificationMode(VerificationModeFactory.atMost(maxNumberOfInvocations));
     }
diff --git a/src/main/java/org/mockito/verification/VerificationAfterDelay.java b/src/main/java/org/mockito/verification/VerificationAfterDelay.java
index b48cb6ba45..1b88ec1fad 100644
--- a/src/main/java/org/mockito/verification/VerificationAfterDelay.java
+++ b/src/main/java/org/mockito/verification/VerificationAfterDelay.java
@@ -49,6 +49,12 @@ public interface VerificationAfterDelay extends VerificationMode {
      */
     VerificationMode atLeast(int minNumberOfInvocations);
 
+    /**
+     * Verifies that there is  most 1 invocation during the given period. This will wait the full period given,
+     * unless too many invocations occur (in which case there will be an immediate failure)
+     */
+    VerificationMode atMostOnce();
+
     /**
      * Verifies that there is are most N invocations during the given period. This will wait the full period given,
      * unless too many invocations occur (in which case there will be an immediate failure)


Test patch:
diff --git a/src/test/java/org/concurrentmockito/ThreadVerifiesContinuoslyInteractingMockTest.java b/src/test/java/org/concurrentmockito/ThreadVerifiesContinuouslyInteractingMockTest.java
similarity index 94%
rename from src/test/java/org/concurrentmockito/ThreadVerifiesContinuoslyInteractingMockTest.java
rename to src/test/java/org/concurrentmockito/ThreadVerifiesContinuouslyInteractingMockTest.java
index 0f91bb3202..2cf6c5bcde 100644
--- a/src/test/java/org/concurrentmockito/ThreadVerifiesContinuoslyInteractingMockTest.java
+++ b/src/test/java/org/concurrentmockito/ThreadVerifiesContinuouslyInteractingMockTest.java
@@ -14,7 +14,7 @@
 import static org.mockito.Mockito.verify;
 
 //this test exposes the problem most of the time
-public class ThreadVerifiesContinuoslyInteractingMockTest extends TestBase {
+public class ThreadVerifiesContinuouslyInteractingMockTest extends TestBase {
 
     @Mock private IMethods mock;
 
diff --git a/src/test/java/org/mockitousage/stubbing/DeepStubbingTest.java b/src/test/java/org/mockitousage/stubbing/DeepStubbingTest.java
index 0e574f0c5e..82753d1de2 100644
--- a/src/test/java/org/mockitousage/stubbing/DeepStubbingTest.java
+++ b/src/test/java/org/mockitousage/stubbing/DeepStubbingTest.java
@@ -280,7 +280,7 @@ public void times_never_atLeast_atMost_verificationModes_should_work() {
 
         verify(person.getAddress("the docks").getStreet(), times(3)).getName();
         verify(person.getAddress("the docks").getStreet(Locale.CHINESE), never()).getName();
-        verify(person.getAddress("the docks").getStreet(Locale.ITALIAN), atMost(1)).getName();
+        verify(person.getAddress("the docks").getStreet(Locale.ITALIAN), atMostOnce()).getName();
     }
 
 
diff --git a/src/test/java/org/mockitousage/verification/AtMostXVerificationTest.java b/src/test/java/org/mockitousage/verification/AtMostXVerificationTest.java
index 2756ef8c71..d7a4d92c50 100644
--- a/src/test/java/org/mockitousage/verification/AtMostXVerificationTest.java
+++ b/src/test/java/org/mockitousage/verification/AtMostXVerificationTest.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.atMost;
+import static org.mockito.Mockito.atMostOnce;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -37,7 +38,7 @@ public void shouldVerifyAtMostXTimes() throws Exception {
         verify(mock, atMost(3)).clear();
 
         try {
-            verify(mock, atMost(1)).clear();
+            verify(mock, atMostOnce()).clear();
             fail();
         } catch (MoreThanAllowedActualInvocations e) {}
     }
@@ -69,7 +70,7 @@ public void shouldPrintDecentMessage() throws Exception {
         mock.clear();
 
         try {
-            verify(mock, atMost(1)).clear();
+            verify(mock, atMostOnce()).clear();
             fail();
         } catch (MoreThanAllowedActualInvocations e) {
             assertEquals("\nWanted at most 1 time but was 2", e.getMessage());
@@ -82,7 +83,7 @@ public void shouldNotAllowInOrderMode() throws Exception {
         InOrder inOrder = inOrder(mock);
 
         try {
-            inOrder.verify(mock, atMost(1)).clear();
+            inOrder.verify(mock, atMostOnce()).clear();
             fail();
         } catch (MockitoException e) {
             assertEquals("AtMost is not implemented to work with InOrder", e.getMessage());