Unit Test

1. Gradle Dependencies: 

// https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.10.2'
// https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.10.2'
// https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params
testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-params', version: '5.10.2'
// https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter

testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.10.2' 


this will replace all of them:

// https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter

testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2'


Mockito dependency:

// https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter

testImplementation group: 'org.mockito', name: 'mockito-junit-jupiter', version: '5.11.0'



package az.etibarli.mockito1;

public class Calculator {

public int integerDivision(int dividend, int divisor) {
return dividend / divisor;
}

public int integerSubtraction(int minuend, int subtrahend) {
return minuend - subtrahend;
}

}


package az.etibarli.mockito1;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class CalculatorTest {

@Test
void integerDivision() {
Calculator calculator = new Calculator();
int result = calculator.integerDivision(4, 2);
assertEquals(2, result, "4 divided by 2 success");
}

@Test
void integerSubtraction() {
Calculator calculator = new Calculator();
int minuend = 33;
int subrahend = 1;
int expectedResult = 34;

int actualResult = calculator.integerSubtraction(minuend, subrahend);
assertEquals(expectedResult, actualResult,
() -> minuend + "-" + subrahend + " did not produce " + expectedResult);
}

}


Different types of tests:

package az.etibarli.mockito1;

import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

@DisplayName("Test Math operation in Calculator class")
public class CalculatorTest {

Calculator calculator;

@BeforeAll
static void setup() {
System.out.println("Executing @BeforeAll method.");
}

@AfterAll
static void cleanup() {
System.out.println("Executing @AfterAll method.");
}

@BeforeEach
void beforeEachTestMethod() {
calculator = new Calculator();
System.out.println("Executing @BeforeEach method");
}

@AfterEach
void afterEachTestMethod() {
System.out.println("Executing @AfterEach method.");
}

@Test
@DisplayName("4 / 2 = 2")
void testIntegerDivision_WhenFourIsDividedByTwo_ShouldReturnTwo() {
System.out.println("Running 4 / 2");
// arrange = given
int dividend = 4;
int divisor = 2;
int expectedResult = 2;

// act = when
int actualResult = calculator.integerDivision(dividend, divisor);

// assert = then
assertEquals(expectedResult, actualResult, "4 divided by 2 success");
}

@Test
// @Disabled("TODO: need to be fixed")
@DisplayName("Division by zero")
void testIntegerDivision_WhenDividendIsDividedByZero_ShouldThrowArithmeticException() {
// arrange = given
int dividend = 4;
int divisor = 1;
String expectedExceptionMessage = "/ by zero";

// act & assert
ArithmeticException actualException = assertThrows(ArithmeticException.class, () -> {
calculator.integerDivision(dividend, divisor);
}, "exception");

// assert
assertEquals(expectedExceptionMessage, actualException.getLocalizedMessage(),
"Unexpected exception message");
}

// @Test
@DisplayName("Test 33 - 1 = 32")
@ParameterizedTest
@MethodSource("integerSubtractionInputParameters")
void integerSubtraction(int minuend, int subtrahend, int expectedResult) {
int actualResult = calculator.integerSubtraction(minuend, subtrahend);
assertEquals(expectedResult, actualResult,
() -> minuend + "-" + subtrahend + " did not produce " + expectedResult);
}

private static Stream<Arguments> integerSubtractionInputParameters() {
return Stream.of(
Arguments.of(33, 1, 32),
Arguments.of(24, 1, 23)
);
}
}


another example:

package az.etibarli.mockito1;

import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;

import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.*;

@DisplayName("Test Math operation in Calculator class")
public class CalculatorTest {

Calculator calculator;

@BeforeAll
static void setup() {
System.out.println("Executing @BeforeAll method.");
}

@AfterAll
static void cleanup() {
System.out.println("Executing @AfterAll method.");
}

@BeforeEach
void beforeEachTestMethod() {
calculator = new Calculator();
System.out.println("Executing @BeforeEach method");
}

@AfterEach
void afterEachTestMethod() {
System.out.println("Executing @AfterEach method.");
}

@Test
@DisplayName("4 / 2 = 2")
void testIntegerDivision_WhenFourIsDividedByTwo_ShouldReturnTwo() {
System.out.println("Running 4 / 2");
// arrange = given
int dividend = 4;
int divisor = 2;
int expectedResult = 2;

// act = when
int actualResult = calculator.integerDivision(dividend, divisor);

// assert = then
assertEquals(expectedResult, actualResult, "4 divided by 2 success");
}

@Test
// @Disabled("TODO: need to be fixed")
@DisplayName("Division by zero")
void testIntegerDivision_WhenDividendIsDividedByZero_ShouldThrowArithmeticException() {
// arrange = given
int dividend = 4;
int divisor = 1;
String expectedExceptionMessage = "/ by zero";

// act & assert
ArithmeticException actualException = assertThrows(ArithmeticException.class, () -> {
calculator.integerDivision(dividend, divisor);
}, "exception");

// assert
assertEquals(expectedExceptionMessage, actualException.getLocalizedMessage(),
"Unexpected exception message");
}

// @Test
@DisplayName("Test 33 - 1 = 32")
@ParameterizedTest
// @MethodSource("integerSubtractionInputParameters")
// @MethodSource
@CsvSource({"33, 1, 32", "24, 1, 23"})
void integerSubtraction(int minuend, int subtrahend, int expectedResult) {
int actualResult = calculator.integerSubtraction(minuend, subtrahend);
assertEquals(expectedResult, actualResult,
() -> minuend + "-" + subtrahend + " did not produce " + expectedResult);
}

@ParameterizedTest
@ValueSource(strings = {"John", "Kate", "Alice"})
void valueSourceDemonstration(String firstName) {
System.out.println(firstName);
assertNotNull(firstName);
}

private static Stream<Arguments> integerSubtraction() {
return Stream.of(
Arguments.of(33, 1, 32),
Arguments.of(24, 1, 23)
);
}
}



--- Repeated Tests:

package az.etibarli.mockito1;

import org.junit.jupiter.api.*;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class DemoRepeatedTest {

Calculator calculator;

@BeforeEach
void beforeEachTestMethod() {
calculator = new Calculator();
System.out.println("Executing @BeforeEach method.");
}

@RepeatedTest(3)
@DisplayName("Division by zero")
void testIntegerDivision_WhenDividendIsDividedByZero_ShouldThrowArithmeticException(
RepetitionInfo repetitionInfo, TestInfo testInfo) {
System.out.println("Running Division by zero");
System.out.println("Running " + testInfo.getTestMethod().get().getName());
System.out.println("Repetition # " + repetitionInfo.getCurrentRepetition() +
" of " + repetitionInfo.getTotalRepetitions());
// arrange = given
int dividend = 4;
int divisor = 0;
String expectedExceptionMessage = "/ by zero";

// act & assert
ArithmeticException actualException = assertThrows(ArithmeticException.class, () -> {
calculator.integerDivision(dividend, divisor);
}, "exception");

// assert
assertEquals(expectedExceptionMessage, actualException.getLocalizedMessage(),
"Unexpected exception message");
}
}


---Method Order: random

package az.etibarli.mockito1;

import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

@TestMethodOrder(MethodOrderer.Random.class)
public class MethodOrderedRandomlyTest {

@Test
void testA() {
System.out.println("Running test A");
}

@Test
void testB() {
System.out.println("Running test B");
}

@Test
void testC() {
System.out.println("Running test C");
}

@Test
void testD() {
System.out.println("Running test D");
}

}


---Method Order: Order by name

package az.etibarli.mockito1;

import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

@TestMethodOrder(MethodOrderer.MethodName.class)
public class MethodOrderedByNameTest {

@Test
void testD() {
System.out.println("Running test D");
}

@Test
void testA() {
System.out.println("Running test A");
}

@Test
void testB() {
System.out.println("Running test B");
}

@Test
void testC() {
System.out.println("Running test C");
}

}


--- Test instance: Per method

package az.etibarli.mockito1;

import org.junit.jupiter.api.*;

@TestInstance(TestInstance.Lifecycle.PER_METHOD)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class MethodOrderedByOrderIndexTest {

StringBuilder completed = new StringBuilder("");

@AfterEach
void afterEach() {
System.out.println("The state of instance object is: " + completed);
}

@Order(1)
@Test
void testA() {
System.out.println("Running test A");
completed.append("1");
}

@Order(2)
@Test
void testB() {
System.out.println("Running test B");
completed.append("2");
}

@Order(3)
@Test
void testC() {
System.out.println("Running test C");
completed.append("3");
}

@Order(4)
@Test
void testD() {
System.out.println("Running test D");
completed.append("4");
}

}


--- Test instance: Per class

package az.etibarli.mockito1;

import org.junit.jupiter.api.*;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class MethodOrderedByOrderIndexTest {

StringBuilder completed = new StringBuilder("");

@AfterEach
void afterEach() {
System.out.println("The state of instance object is: " + completed);
}

@Order(1)
@Test
void testA() {
System.out.println("Running test A");
completed.append("1");
}

@Order(2)
@Test
void testB() {
System.out.println("Running test B");
completed.append("2");
}

@Order(3)
@Test
void testC() {
System.out.println("Running test C");
completed.append("3");
}

@Order(4)
@Test
void testD() {
System.out.println("Running test D");
completed.append("4");
}

}


--- Simple test with data:

package az.etibarli.mockito1.io;

import java.util.Map;

public interface UsersDatabase {
void init();
void close();
Map save(String userId, Map userDetails);
Map update(String userId, Map user);
Map find(String userId);
void delete(String userId);
}


package az.etibarli.mockito1.io;

import java.util.HashMap;
import java.util.Map;

public class UsersDatabaseMapImpl implements UsersDatabase {

Map<String, Map> users;

@Override
public void init() {
users = new HashMap<>();
}

@Override
public void close() {
users = null;
}

@Override
public Map save(String userId, Map userDetails) {
return users.put(userId, userDetails);
}

@Override
public Map update(String userId, Map user) {
users.put(userId, user);
return users.get(userId);
}

@Override
public Map find(String userId) {
return users.get(userId);
}

@Override
public void delete(String userId) {
users.remove(userId);
}
}


package az.etibarli.mockito1.service;

import java.util.Map;

public interface UserService {
String createUser(Map userDetails);
Map updateUser(String userId, Map userDetails);
Map getUserDetails(String userId);
void deleteUser(String userId);
}


package az.etibarli.mockito1.service;


import az.etibarli.mockito1.io.UsersDatabase;

import java.util.Map;
import java.util.UUID;

public class UserServiceImpl implements UserService {

UsersDatabase usersDatabase;

public UserServiceImpl(UsersDatabase usersDatabase) {
this.usersDatabase = usersDatabase;
}

@Override
public String createUser(Map userDetails) {
String userId = UUID.randomUUID().toString();
userDetails.put("userId", userId);
usersDatabase.save(userId, userDetails);
return userId;
}

@Override
public Map updateUser(String userId, Map userDetails) {
Map existingUser = usersDatabase.find(userId);
if (existingUser == null) throw new IllegalArgumentException("User not found");

existingUser.put("firstName", userDetails.get("firstName"));
existingUser.put("lastName", userDetails.get("lastName"));

return usersDatabase.update(userId, existingUser);
}

@Override
public Map getUserDetails(String userId) {
return usersDatabase.find(userId);
}

@Override
public void deleteUser(String userId) {
Map existingUser = usersDatabase.find(userId);
if (existingUser == null) throw new IllegalArgumentException("User not found");

usersDatabase.delete(userId);
}

}


package az.etibarli.mockito1;

import az.etibarli.mockito1.io.UsersDatabase;
import az.etibarli.mockito1.io.UsersDatabaseMapImpl;
import az.etibarli.mockito1.service.UserService;
import az.etibarli.mockito1.service.UserServiceImpl;
import org.junit.jupiter.api.*;

import java.util.HashMap;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class UserServiceImplTest {

UsersDatabase usersDatabase;
UserService userService;
String createdUserId = "";

@BeforeAll
void setUp() {
// Create & initialize database
usersDatabase = new UsersDatabaseMapImpl();
usersDatabase.init();
userService = new UserServiceImpl(usersDatabase);
}

@AfterAll
void cleanUp() {
// Close database
// Delete database
usersDatabase.close();
}

@Test
@Order(1)
@DisplayName("Create User works")
void testCreateUser_whenProvideWithValidDetails_returnsUserId() {
// arrange
Map<String, String> user = new HashMap<>();
user.put("firstName", "Sergey");
user.put("lastName", "Kargopolov");

// act
createdUserId = userService.createUser(user);

// assert
assertNotNull(createdUserId, "User id should not be null");
}

@Test
@Order(2)
@DisplayName("Update User works")
void testUpdateUser_whenProvideWithValidDetails_returnsUpdatedUserDetails() {
// arrange
Map<String, String> newUserDetails = new HashMap<>();
newUserDetails.put("firstName", "John");
newUserDetails.put("lastName", "kargopolov");

// act
Map updatedUserDetails = userService.updateUser(createdUserId, newUserDetails);

// assert
assertEquals(newUserDetails.get("firstName"), updatedUserDetails.get("firstName"),
"Returned value of user's first name is incorrect");
assertEquals(newUserDetails.get("lastName"), updatedUserDetails.get("lastName"),
"Returned value of user's last name is incorrect");
}

@Test
@Order(3)
@DisplayName("Find User works")
void testGetUserDetails_whenProvideWithValidUserId_returnsUserDetails() {
// act
Map userDetails = userService.getUserDetails(createdUserId);

// assert
assertNotNull(userDetails, "User details should not be null");
assertEquals(createdUserId, userDetails.get("userId"),
"Returned user details contains incorrect user id");
}

@Test
@Order(4)
@DisplayName("Delete User works")
void testDeleteUser_whenProvideWithValidUserId_returnsUserDetails() {
// act
userService.deleteUser(createdUserId);

// assert
assertNull(userService.getUserDetails(createdUserId), "User should not been found");
}

}























Комментарии

Популярные сообщения из этого блога

IoC:ApplicationContext, BeanFactory. Bean

Lesson1: JDK, JVM, JRE

Lesson_2: Operations in Java