Skip to content

Commit 561c06b

Browse files
Added auth usecase tests
1 parent 8a2baeb commit 561c06b

File tree

9 files changed

+449
-211
lines changed

9 files changed

+449
-211
lines changed

Tutorial2-2Mockito-BDD/src/test/java/com/smarttoolfactory/tutorial2_2mockito_bdd/BDDMockitoUnitTest.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,14 @@
99
import org.mockito.invocation.InvocationOnMock;
1010

1111
import static org.junit.Assert.fail;
12-
import static org.mockito.BDDMockito.*;
12+
import static org.mockito.BDDMockito.any;
13+
import static org.mockito.BDDMockito.eq;
14+
import static org.mockito.BDDMockito.given;
15+
import static org.mockito.BDDMockito.mock;
16+
import static org.mockito.BDDMockito.never;
17+
import static org.mockito.BDDMockito.then;
18+
import static org.mockito.BDDMockito.verify;
19+
import static org.mockito.BDDMockito.willThrow;
1320

1421

1522
public class BDDMockitoUnitTest {
@@ -52,6 +59,7 @@ public void givenValidContactName_whenSearchInPhoneBook_thenRetunPhoneNumber() {
5259

5360
@Test
5461
public void givenInvalidContactName_whenSearch_thenRetunNull() {
62+
5563
given(phoneBookRepository.contains(xContactName)).willReturn(false);
5664

5765
String phoneNumber = phoneBookService.search(xContactName);

Tutorial6-1TestDrivenDevelopment/src/main/java/com/smarttoolfactory/tutorial6_1testdrivendevelopment/model/login/LoginRepo.kt

Lines changed: 0 additions & 6 deletions
This file was deleted.

Tutorial6-1TestDrivenDevelopment/src/main/java/com/smarttoolfactory/tutorial6_1testdrivendevelopment/model/login/LoginUseCase.kt

Lines changed: 0 additions & 25 deletions
This file was deleted.

Tutorial6-1TestDrivenDevelopment/src/main/java/com/smarttoolfactory/tutorial6_1testdrivendevelopment/model/login_auth/AccountManager.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@ package com.smarttoolfactory.tutorial6_1testdrivendevelopment.model.login_auth
22

33
interface AccountManager {
44

5+
fun saveToken(token: String): Boolean
6+
7+
fun getToken(): String?
8+
9+
fun deleteToken()
10+
511
}
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,205 @@
11
package com.smarttoolfactory.tutorial6_1testdrivendevelopment.model.login_auth
22

3+
import com.smarttoolfactory.tutorial6_1testdrivendevelopment.model.login_auth.AuthenticationState.*
4+
35
class AuthUseCase(
46
private val authRepository: AuthRepository,
5-
private val userManager: AccountManager
7+
private val accountManager: AccountManager
68
) {
79

10+
private var loginAttempt = 0
11+
812
/*
9-
STEP 1: Throw exception for test to compile and fail
13+
🔥 STEP 2: Throw exception for test to compile and fail
14+
1015
*/
1116
// fun login(
1217
// userName: String,
1318
// password: String,
1419
// rememberMe: Boolean = false
1520
// ): AuthenticationState {
16-
// throw NullPointerException()
21+
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
1722
// }
1823

1924

2025
/*
21-
STEP3: Check if username or password is empty
26+
🔥 STEP3: Add code to return EMPTY_FIELD_ERROR if username or password is empty
2227
*/
23-
fun login(
28+
// fun login(
29+
// userName: String,
30+
// password: String,
31+
// rememberMe: Boolean = false
32+
// ): AuthenticationState {
33+
//
34+
//
35+
// if (userName.isNullOrBlank() || password.isNullOrBlank()) {
36+
// return EMPTY_FIELD_ERROR
37+
// } else {
38+
// TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
39+
// }
40+
//
41+
// }
42+
43+
44+
/*
45+
🔥 STEP3: Add code to return EMPTY_FIELD_ERROR if password length does not match
46+
*/
47+
// fun login(
48+
// userName: String,
49+
// password: String,
50+
// rememberMe: Boolean = false
51+
// ): AuthenticationState {
52+
//
53+
// return if (userName.isNullOrBlank() || password.isNullOrBlank()) {
54+
// return EMPTY_FIELD_ERROR
55+
// } else if (!checkIfPasswordIsValid(password)) {
56+
// INVALID_FIELD_ERROR
57+
// } else {
58+
// throw TestFailedException()
59+
// }
60+
//
61+
// }
62+
63+
/*
64+
🔥 STEP5: Add code to return EMPTY_FIELD_ERROR if username is not valid expression
65+
*/
66+
// fun login(
67+
// userName: String,
68+
// password: String,
69+
// rememberMe: Boolean = false
70+
// ): AuthenticationState {
71+
//
72+
// return if (userName.isNullOrBlank() || password.isNullOrBlank()) {
73+
// return EMPTY_FIELD_ERROR
74+
// } else if (!checkUserNameIsValid(userName) || !checkIfPasswordIsValid(password)) {
75+
// INVALID_FIELD_ERROR
76+
// } else {
77+
// throw TestFailedException()
78+
// }
79+
//
80+
// }
81+
82+
/*
83+
🔥 STEP7-9: Add code to return invalid authentication when user name or password is wrong
84+
*/
85+
// fun login(
86+
// userName: String,
87+
// password: String,
88+
// rememberMe: Boolean = false
89+
// ): AuthenticationState {
90+
//
91+
// return if (userName.isNullOrBlank() || password.isNullOrBlank()) {
92+
// return EMPTY_FIELD_ERROR
93+
// } else if (!checkUserNameIsValid(userName) || !checkIfPasswordIsValid(password)) {
94+
// INVALID_FIELD_ERROR
95+
// } else {
96+
// // Concurrent Authentication via mock that returns AUTHENTICATED, or FAILED_AUTHENTICATION
97+
//
98+
// val authResponse =
99+
// authRepository.login(userName, password, rememberMe)
100+
//
101+
// val authenticationPass = authResponse?.authenticated ?: false
102+
//
103+
// if (authenticationPass) {
104+
// SUCCESSFUL_AUTHENTICATION
105+
//
106+
// } else {
107+
// FAILED_AUTHENTICATION
108+
// }
109+
// }
110+
//
111+
// }
112+
113+
114+
/*
115+
🔥 STEP 11 Add code to check maximum number of attempts
116+
*/
117+
fun login(
24118
userName: String,
25119
password: String,
26120
rememberMe: Boolean = false
27121
): AuthenticationState {
28-
if (userName.isNullOrBlank() || password.isNullOrBlank()) {
29-
return AuthenticationState.EMPTY_FIELDS
30-
}else {
31-
throw NullPointerException()
32-
}
33122

123+
return if (userName.isNullOrBlank() || password.isNullOrBlank()) {
124+
return EMPTY_FIELD_ERROR
125+
} else if (!checkUserNameIsValid(userName) || !checkIfPasswordIsValid(password)) {
126+
INVALID_FIELD_ERROR
127+
} else {
128+
// Concurrent Authentication via mock that returns AUTHENTICATED, or FAILED_AUTHENTICATION
129+
130+
val authenticationPass = getAccountResponse(userName, password, rememberMe)
131+
132+
133+
if (authenticationPass) {
134+
135+
loginAttempt = 0
136+
SUCCESSFUL_AUTHENTICATION
137+
138+
} else {
139+
140+
loginAttempt++
141+
142+
if (loginAttempt >= MAX_LOGIN_ATTEMPT) {
143+
MAX_NUMBER_OF_ATTEMPTS_ERROR
144+
} else {
145+
FAILED_AUTHENTICATION
146+
}
147+
}
148+
}
149+
150+
}
151+
152+
private fun getAccountResponse(
153+
userName: String,
154+
password: String,
155+
rememberMe: Boolean
156+
): Boolean {
157+
158+
val authResponse =
159+
authRepository.login(userName, password)
160+
161+
val authenticationPass = authResponse?.authenticated ?: false
162+
163+
164+
saveToken(authResponse, rememberMe)
165+
166+
return authenticationPass
167+
}
168+
169+
/*
170+
🔥 STEP 13 Add code to save token when remember me is selected
171+
*/
172+
private fun saveToken(
173+
authResponse: AuthResponse?,
174+
rememberMe: Boolean
175+
) {
176+
authResponse?.token?.let {
177+
if (rememberMe) accountManager.saveToken(it)
178+
}
179+
}
180+
181+
182+
private fun checkUserNameIsValid(field: String): Boolean {
183+
return field.length > 15 && field.endsWith("@example.com")
184+
185+
}
186+
187+
private fun checkIfPasswordIsValid(field: String): Boolean {
188+
return field.length in 6..10
34189
}
35190

36-
}
191+
192+
/*
193+
🔥 STEP 15 Add code to get token when it's saved
194+
*/
195+
fun getToken(): String? {
196+
return accountManager.getToken()
197+
198+
}
199+
200+
fun logOut() {
201+
accountManager.deleteToken()
202+
}
203+
204+
}
205+

Tutorial6-1TestDrivenDevelopment/src/main/java/com/smarttoolfactory/tutorial6_1testdrivendevelopment/model/login_auth/AuthenticationState.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ enum class AuthenticationState {
88
/**
99
* The user has authenticated successfully
1010
*/
11-
AUTHENTICATED,
11+
SUCCESSFUL_AUTHENTICATION,
1212

1313
/**
1414
* User left user name or password field empty
1515
*/
16-
EMPTY_FIELDS,
16+
EMPTY_FIELD_ERROR,
1717
/**
1818
* Password or username type mismatch. Less than required length and/or missing alpha-numeric regex
1919
*/
20-
INVALID_FIELDS,
20+
INVALID_FIELD_ERROR,
2121
/**
2222
* Authentication failed
2323
*/
@@ -26,7 +26,9 @@ enum class AuthenticationState {
2626
/**
2727
* Max number of invalid login attempts occurred
2828
*/
29-
MAX_NUMBER_OF_INVALID_ATTEMPTS
29+
MAX_NUMBER_OF_ATTEMPTS_ERROR
3030
}
3131

32-
const val MAX_LOGIN_ATTEMPT = 3
32+
const val MAX_LOGIN_ATTEMPT = 3
33+
const val FIELD_LENGTH_MIN = 6
34+
const val FIELD_LENGTH_MAX = 10

Tutorial6-1TestDrivenDevelopment/src/test/java/com/smarttoolfactory/tutorial6_1testdrivendevelopment/AssertExtensions.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ package com.smarttoolfactory.tutorial6_1testdrivendevelopment
22

33
import org.junit.jupiter.api.Assertions
44

5-
infix fun Any.assertEquals(any: Any) {
5+
infix fun Any.assertThatEquals(any: Any) {
66
Assertions.assertEquals(this, any)
77
}
88

9-
infix fun Any.assertNotEquals(any: Any) {
9+
infix fun Any.assertThatNotEquals(any: Any) {
1010
Assertions.assertNotEquals(this, any)
1111
}

0 commit comments

Comments
 (0)