Intro
I’m writing tests for a RESTful JPA Springboot API but I am struggling to set it up. I have set a simple model, repository and service layer
Model
package id.ac.ui.cs.advpro.app.models;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import lombok.*;
import java.util.Date;
@Entity
@Table(name = "transactions")
public class TransactionModel {
@Id
@GeneratedValue(strategy = jakarta.persistence.GenerationType.IDENTITY)
@Column(name = "id")
@NotNull
@Setter
@Getter
private long id;
@Column(name = "voucher_id")
@Setter
@Getter
private long voucherId;
@Column(name = "transaction_date")
@NotNull
@Setter
@Getter
private Date transactionDate;
@Column(name = "total_amount")
@NotNull
@Setter
@Getter
private long totalAmount;
public TransactionModel() {
}
public TransactionModel(long id, long voucherId, Date transactionDate, long totalAmount) {
this.id = id;
this.voucherId = voucherId;
this.transactionDate = transactionDate;
this.totalAmount = totalAmount;
}
}
Repository
package id.ac.ui.cs.advpro.app.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import id.ac.ui.cs.advpro.app.models.TransactionModel;
@Repository
public interface TransactionRepository extends JpaRepository<TransactionModel, Long>{
}
Service
package id.ac.ui.cs.advpro.app.service.impl;
import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Service;
import id.ac.ui.cs.advpro.app.models.TransactionModel;
import id.ac.ui.cs.advpro.app.repository.TransactionRepository;
import id.ac.ui.cs.advpro.app.service.TransactionService;
@Service
public class TransactionServiceImpl implements TransactionService{
private final TransactionRepository repository;
public TransactionServiceImpl(TransactionRepository repository) {
this.repository = repository;
}
//C(reate)
@Override
public TransactionModel addTransaction(TransactionModel transaction) {
return repository.save(transaction);
};
//R(ead)
@Override
public List<TransactionModel> findAllTransaction() {
return repository.findAll();
};
@Override
public Optional<TransactionModel> findById(Long id) {
return repository.findById(id);
};
//U(pdate)
@Override
public TransactionModel updateTransaction(TransactionModel transaction) {
return repository.save(transaction);
};
//D(elete)
@Override
public void deleteTransaction(Long id) {
repository.deleteById(id);
};
}
Attempts
Here are my attempts at making tests for the service layer. I have looked into previously answered and suggested solutions here but none seem to work.
package id.ac.ui.cs.advpro.app.service.impl;
import id.ac.ui.cs.advpro.app.models.TransactionModel;
import id.ac.ui.cs.advpro.app.repository.TransactionRepository;
import java.util.Date;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.Assertions;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.InjectMocks;
import org.mockito.Spy;
@ExtendWith(MockitoExtension.class)
public class TransactionServiceImplTest {
@InjectMocks
private TransactionServiceImpl transactionService;
@Spy
private TransactionRepository transactionRepository;
@BeforeEach
public void setUp() {
TransactionModel transaction = new TransactionModel(1, 1, new Date(), 100000);
transactionService.addTransaction(transaction);
}
@Test
public void testGetAllTransactions() {
Assertions.assertEquals(1, transactionService.findAllTransaction().size());
}
}
the test class successfully injected the repository into the service class but
transactionService.addTransaction(transaction);
returns null, it calls
repository.save(transaction);
which the docs said should never return null.
<TransactionModel> TransactionModel org.springframework.data.repository.CrudRepository.save(TransactionModel entity)
Saves a given entity. Use the returned instance for further operations as the save operation might have changed the entity instance completely.
Type Parameters:
Parameters:
entity must not be null.
Returns:
the saved entity; will never be null.
Throws:
IllegalArgumentException - in case the given entity is null.
OptimisticLockingFailureException - when the entity uses optimistic locking and has a version attribute with a different value from that found in the persistence store. Also thrown if the entity is assumed to be present but does not exist in the database.
thus the test fails because nothing is added to the repository.
Question
How should I write tests for the repository and service layers for my project?