View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package mockit;
7   
8   import static org.junit.jupiter.api.Assertions.assertThrows;
9   
10  import mockit.integration.junit5.JMockitExtension;
11  import mockit.internal.expectations.invocation.MissingInvocation;
12  import mockit.internal.expectations.invocation.UnexpectedInvocation;
13  
14  import org.junit.jupiter.api.Test;
15  import org.junit.jupiter.api.extension.ExtendWith;
16  
17  /**
18   * This class tests the invocation constraints for mocked methods using JMockit. It verifies that the @Mock annotation's
19   * invocations, minInvocations, and maxInvocations parameters work correctly by expecting specific exceptions or
20   * allowing calls within limits.
21   */
22  @ExtendWith(JMockitExtension.class)
23  class InvocationConstraintsTest {
24  
25      /**
26       * A simple class under test that depends on a Collaborator.
27       */
28      static class CodeUnderTest {
29          private final Collaborator dependency = new Collaborator();
30  
31          void doSomething() {
32              dependency.provideSomeService();
33          }
34      }
35  
36      /**
37       * A collaborator class that provides a service, throwing an exception in the real implementation.
38       */
39      static class Collaborator {
40          void provideSomeService() {
41              throw new RuntimeException("Real provideSomeService() called");
42          }
43      }
44  
45      final CodeUnderTest codeUnderTest = new CodeUnderTest();
46  
47      // Tests for @Mock(invocations = N) with different call counts
48  
49      @Test
50      void testInvocationsWith0Calls() {
51          assertThrows(MissingInvocation.class, () -> {
52              new MockUp<Collaborator>() {
53                  @Mock(invocations = 1)
54                  void provideSomeService() {
55                  }
56              };
57          });
58      }
59  
60      @Test
61      void testInvocationsWith1Call() {
62          new MockUp<Collaborator>() {
63              @Mock(invocations = 1)
64              void provideSomeService() {
65              }
66          };
67  
68          // Call 1 time
69          codeUnderTest.doSomething();
70      }
71  
72      @Test
73      void testInvocationsWith2Calls() {
74          new MockUp<Collaborator>() {
75              @Mock(invocations = 1)
76              void provideSomeService() {
77              }
78          };
79  
80          // Call 1 time - OK
81          codeUnderTest.doSomething();
82  
83          // Call 2nd time - UnexpectedInvocation will be thrown immediately
84          assertThrows(UnexpectedInvocation.class, () -> {
85              codeUnderTest.doSomething();
86          });
87      }
88  
89      // Tests for @Mock(minInvocations = N) with different call counts
90  
91      @Test
92      void testMinInvocationsWith0Calls() {
93          assertThrows(MissingInvocation.class, () -> {
94              new MockUp<Collaborator>() {
95                  @Mock(minInvocations = 1)
96                  void provideSomeService() {
97                  }
98              };
99          });
100     }
101 
102     @Test
103     void testMinInvocationsWith1Call() {
104         new MockUp<Collaborator>() {
105             @Mock(minInvocations = 1)
106             void provideSomeService() {
107             }
108         };
109 
110         // Call 1 time
111         codeUnderTest.doSomething();
112     }
113 
114     @Test
115     void testMinInvocationsWith2Calls() {
116         new MockUp<Collaborator>() {
117             @Mock(minInvocations = 1)
118             void provideSomeService() {
119             }
120         };
121 
122         // Call 2 times
123         codeUnderTest.doSomething();
124         codeUnderTest.doSomething();
125     }
126 
127     // Tests for @Mock(maxInvocations = N) with different call counts
128 
129     @Test
130     void testMaxInvocationsWith0Calls() {
131         new MockUp<Collaborator>() {
132             @Mock(maxInvocations = 1)
133             void provideSomeService() {
134             }
135         };
136 
137         // Call 0 times
138     }
139 
140     @Test
141     void testMaxInvocationsWith1Call() {
142         new MockUp<Collaborator>() {
143             @Mock(maxInvocations = 1)
144             void provideSomeService() {
145             }
146         };
147 
148         codeUnderTest.doSomething(); // Call 1 time
149     }
150 
151     @Test
152     void testMaxInvocationsWith2Calls() {
153         new MockUp<Collaborator>() {
154             @Mock(maxInvocations = 1)
155             void provideSomeService() {
156             }
157         };
158 
159         // Call 1 time - OK
160         codeUnderTest.doSomething();
161 
162         // Call 2nd time - UnexpectedInvocation will be thrown immediately
163         assertThrows(UnexpectedInvocation.class, () -> {
164             codeUnderTest.doSomething();
165         });
166     }
167 
168 }