Careeroza
Unit Tests with JUnit 5 and Mockito
Testing the Service
import static org.assertj.core.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.*;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class ProductServiceTest {
@Mock ProductRepository repo;
@Spy ProductMapper mapper = new ProductMapperImpl(); // real MapStruct mapper
@InjectMocks ProductService service;
@Test
void createSavesNewProduct() {
var req = new CreateProductRequest("ELE-1001", "Wireless Mouse", "2.4 GHz",
new BigDecimal("799.00"), 120, "Electronics");
when(repo.existsBySku("ELE-1001")).thenReturn(false);
when(repo.save(any(Product.class))).thenAnswer(inv -> {
Product p = inv.getArgument(0);
p.setId(1L);
return p;
});
ProductResponse res = service.create(req);
assertThat(res.id()).isEqualTo(1L);
assertThat(res.inStock()).isTrue();
verify(repo).save(any(Product.class));
}
@Test
void createRejectsDuplicateSku() {
when(repo.existsBySku("ELE-1001")).thenReturn(true);
var req = new CreateProductRequest("ELE-1001", "Mouse", null, BigDecimal.TEN, 1, "Electronics");
assertThatThrownBy(() -> service.create(req))
.isInstanceOf(DuplicateSkuException.class)
.hasMessage("SKU ELE-1001 already exists");
verify(repo, never()).save(any());
}
}Example
./mvnw test -Dtest=ProductServiceTestExample output
[INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running com.shopease.product.ProductServiceTest [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.412 s [INFO] BUILD SUCCESS
Mockito Cheat Sheet
| Code | Meaning |
|---|---|
when(repo.findById(1L)).thenReturn(Optional.of(p)) | Stub a return value |
when(repo.save(any())).thenThrow(new RuntimeException()) | Stub an exception |
verify(repo).save(p) | Was it called once with p? |
verify(repo, never()).deleteById(any()) | Was it never called? |
ArgumentCaptor<Product> + verify(repo).save(captor.capture()) | Inspect what was passed |
Tip: Name tests after behaviour (createRejectsDuplicateSku), and follow Arrange / Act / Assert inside each test.