View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package jmockit.loginExample.domain.userLogin;
7   
8   import static org.testng.Assert.assertThrows;
9   
10  import mockit.Expectations;
11  import mockit.Mocked;
12  import mockit.Tested;
13  import mockit.Verifications;
14  
15  import org.testng.annotations.Test;
16  
17  import jmockit.loginExample.domain.userAccount.UserAccount;
18  
19  /**
20   * A small TestNG test suite for a single class (<code>LoginService</code>), based on
21   * <a href="http://schuchert.wikispaces.com/Mockito.LoginServiceExample">this article</a>.
22   */
23  public final class LoginServiceNGTest {
24  
25      /** The service. */
26      @Tested
27      LoginService service;
28  
29      /** The account. */
30      @Mocked
31      UserAccount account;
32  
33      /**
34       * This test is redundant, as it exercises the same path as the last test. It cannot simply be removed, because the
35       * last test does not perform the "account.setLoggedIn(true)" verification; if said verification is added there,
36       * however, then this test could be removed without weakening the test suite.
37       *
38       * @throws Exception
39       *             the exception
40       */
41      @Test
42      public void setAccountToLoggedInWhenPasswordMatches() throws Exception {
43          willMatchPassword(true);
44  
45          service.login("john", "password");
46  
47          new Verifications() {
48              {
49                  account.setLoggedIn(true);
50              }
51          };
52      }
53  
54      /**
55       * Will match password.
56       *
57       * @param matches
58       *            the matches
59       */
60      void willMatchPassword(boolean... matches) {
61          new Expectations() {
62              {
63                  account.passwordMatches(anyString);
64                  result = matches;
65              }
66          };
67      }
68  
69      /**
70       * Sets the account to revoked after three failed login attempts.
71       *
72       * @throws Exception
73       *             the exception
74       */
75      @Test
76      public void setAccountToRevokedAfterThreeFailedLoginAttempts() throws Exception {
77          willMatchPassword(false);
78  
79          for (int i = 0; i < 3; i++) {
80              service.login("john", "password");
81          }
82  
83          new Verifications() {
84              {
85                  account.setRevoked(true);
86              }
87          };
88      }
89  
90      /**
91       * This test is also redundant, as it exercises the same path as the previous one. Again, it cannot simply be
92       * removed since the previous test does not verify that "account.setLoggedIn(true)" is never called; if said
93       * verification is added there, however, this test could safely be removed.
94       *
95       * @throws Exception
96       *             the exception
97       */
98      @Test
99      public void notSetAccountLoggedInIfPasswordDoesNotMatch() throws Exception {
100         willMatchPassword(false);
101 
102         service.login("john", "password");
103 
104         new Verifications() {
105             {
106                 account.setLoggedIn(true);
107                 times = 0;
108             }
109         };
110     }
111 
112     /**
113      * Not revoke second account after two failed attempts on first account.
114      *
115      * @throws Exception
116      *             the exception
117      */
118     @Test
119     public void notRevokeSecondAccountAfterTwoFailedAttemptsOnFirstAccount() throws Exception {
120         new Expectations() {
121             {
122                 account.passwordMatches(anyString);
123                 result = false;
124             }
125         };
126 
127         service.login("john", "password");
128         service.login("john", "password");
129         service.login("roger", "password");
130 
131         new Verifications() {
132             {
133                 account.setRevoked(true);
134                 times = 0;
135             }
136         };
137     }
138 
139     /**
140      * Disallow concurrent logins.
141      */
142     @Test
143     public void disallowConcurrentLogins() {
144         willMatchPassword(true);
145 
146         new Expectations() {
147             {
148                 account.isLoggedIn();
149                 result = true;
150             }
151         };
152 
153         assertThrows(AccountLoginLimitReachedException.class, () -> {
154             service.login("john", "password");
155         });
156     }
157 
158     /**
159      * Throw exception if account not found.
160      */
161     @Test
162     public void throwExceptionIfAccountNotFound() {
163         new Expectations() {
164             {
165                 UserAccount.find("roger");
166                 result = null;
167             }
168         };
169 
170         assertThrows(UserAccountNotFoundException.class, () -> {
171             service.login("roger", "password");
172         });
173     }
174 
175     /**
176      * Disallow logging into revoked account.
177      */
178     @Test
179     public void disallowLoggingIntoRevokedAccount() {
180         willMatchPassword(true);
181 
182         new Expectations() {
183             {
184                 account.isRevoked();
185                 result = true;
186             }
187         };
188 
189         assertThrows(UserAccountRevokedException.class, () -> {
190             service.login("john", "password");
191         });
192     }
193 
194     /**
195      * Reset back to initial state after successful login.
196      *
197      * @throws Exception
198      *             the exception
199      */
200     @Test
201     public void resetBackToInitialStateAfterSuccessfulLogin() throws Exception {
202         willMatchPassword(false, false, true, false);
203 
204         service.login("john", "password");
205         service.login("john", "password");
206         service.login("john", "password");
207         service.login("john", "password");
208 
209         new Verifications() {
210             {
211                 account.setRevoked(true);
212                 times = 0;
213             }
214         };
215     }
216 }