Aloha zusammen,
ich versuche mich gerade an neuen Frameworks (Spring Boot & JUnit). Soweit funktioniert alles und wie immer gibt es auch die ein oder andere Straße nach Rom, weswegen ich gerne einmal Feedback sammeln würde in Bezug auf meine Tests/Implementierung.
Prinzipiell habe ich folgende Architektur im Kopf:
JpaRepository <-- ENTITY --> Service(Impl) <-- DTO/ENTITY --> Frontend/Controller/...
Nun ein Beispiel meines Codes. Prinzipiell sollen in der App verschiedene User, welcher innerhalb einer Company zusammenarbeiten können Ihre Inventur (über Produkte) machen können. Späße wie ACL wollte ich im Frontend machen (z.B. User versucht ein produkt anzulegen für eine andere Company zu welcher er nicht zugehörig ist etc).
Meine Service Klasse:
Meine Service Test Klasse:
Meine Fragen:
ich versuche mich gerade an neuen Frameworks (Spring Boot & JUnit). Soweit funktioniert alles und wie immer gibt es auch die ein oder andere Straße nach Rom, weswegen ich gerne einmal Feedback sammeln würde in Bezug auf meine Tests/Implementierung.
Prinzipiell habe ich folgende Architektur im Kopf:
JpaRepository <-- ENTITY --> Service(Impl) <-- DTO/ENTITY --> Frontend/Controller/...
Nun ein Beispiel meines Codes. Prinzipiell sollen in der App verschiedene User, welcher innerhalb einer Company zusammenarbeiten können Ihre Inventur (über Produkte) machen können. Späße wie ACL wollte ich im Frontend machen (z.B. User versucht ein produkt anzulegen für eine andere Company zu welcher er nicht zugehörig ist etc).
Meine Service Klasse:
Java:
@Service
@Transactional
public class ProductService implements IProductService {
@Autowired
private ProductRepository productRepository;
@Autowired
private ICompanyService companyService;
@Override
public Page<Product> getProducts(Company company, Pageable pageable) {
return productRepository.findAllByCompany(company, pageable);
}
@Override
public Product createNewProduct(ProductDto dto) throws Exception {
Product p = new Product();
p.setName(dto.getName());
p.setGtin(dto.getGtin());
p.setArticleNumber(dto.getArticleNumber());
p.setCompany(companyService.findById(dto.getCompanyId()).orElseThrow(Exception::new)); //TODO: proper Exception
p.setPrice(dto.getPrice());
p.setPurchasingPrice(dto.getPurchasingPrice());
return productRepository.save(p);
}
}
Java:
@DataJpaTest
@ExtendWith(MockitoExtension.class)
class ProductServiceTest {
@InjectMocks
private ProductService productService;
@Mock
private ProductRepository productRepository;
@Mock
private CompanyService companyService;
private Company company;
private User user;
@BeforeEach
void setup() {
user = new User();
user.setEmail("hope@junit-test.de");
user.setFirstName("Hope");
user.setLastName("Mikaelson");
user.setPassword("1234567");
company = new Company();
company.setName("BlackRock");
company.setUser(user);
}
@test
void getProductsForCompanyWhenNoProductsExist() {
Pageable p = PageRequest.of(0, 5);
when(productRepository.findAllByCompany(company, p))
.thenReturn(new PageImpl<>(new ArrayList<>(), p, 0));
Page<Product> products = productService.getProducts(company, p);
assertEquals(0, products.getTotalElements());
}
@test
void getProductsForCompany() {
Pageable p = PageRequest.of(0, 5);
List<Product> productList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Product product = new Product();
product.setCompany(company);
product.setName(String.valueOf(i));
product.setArticleNumber("P" + i);
product.setPrice(new BigDecimal("1.99"));
productList.add(product);
}
when(productRepository.findAllByCompany(company, p))
.thenReturn(new PageImpl<>(productList, p, productList.size()));
Page<Product> products = productService.getProducts(company, p);
assertEquals(10, products.getTotalElements());
assertEquals(2, products.getTotalPages());
assertEquals(5, products.getSize());
}
@test
void createNewProduct() throws Exception {
UUID companyUuid = UUID.randomUUID();
ProductDto dto = new ProductDto();
dto.setName("MacBook Air M1 2022");
dto.setPrice(new BigDecimal("1337"));
dto.setArticleNumber("APL-MBA-M1-22");
dto.setCompanyId(companyUuid);
when(companyService.findById(companyUuid)).thenReturn(Optional.ofNullable(company));
productService.createNewProduct(dto);
verify(productRepository, times(1)).save(Mockito.any(Product.class));
}
}
Meine Fragen:
- Macht die Test implementierung so Sinn? Gäbe es optimierungsbedarf?
- Macht es in Spring Boot Sinn Tests für die JPARepository Klassen zu schreiben (für die "custom methoden")?
- Macht der Frontend mix aus DTO/Entity Sinn? Oder sollte der Service Layer nach vorne bereits alles in DTOs übersetzen?
- Verbesserungsvorschläge?