Issue
I'm making a SpringBoot app where I have two classes with many-to-many relationship: User and Plant. I'm using a MySQL database, where I have tables users, plants and a joined table for the two classes user_plants.
I then have a UserRepository interface, where I defined a method for deleting entries from the user_plants table:
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
@Modifying
@Query(value = "DELETE FROM user_plants WHERE user_id = ?1 AND plant_id = ?2", nativeQuery = true)
void deletePlantById(int userId, int plantId);
}
This method is later used in UserService class:
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository){
this.userRepository = userRepository; }
@Transactional
public void deletePlant(int userId, int plantId){
userRepository.deletePlantById(userId, plantId);
}}
I have recently started learning about unit tests and I'm trying to write a unit test for UserRepository. I managed to successfully test all of the default JpaRepository methods, such as getById, findAll etc. However, the test for the method implemented by me always fails.
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
private User user;
@BeforeEach
public void setUp(){
Set<Plant> plantsSet = new LinkedHashSet<>();
plantsSet.add(new Plant(5, "Monstera"));
user = new User(1, "Alice", plantsSet);
userRepository.save(user);
}
@AfterEach
public void clean(){
userRepository.deleteAll();
user = null;
}
@Test
void givenPlantIdAndUserIdShouldDeletePlantOfThatIdFromUserPlants() {
userRepository.deletePlantById(1, 5);
assertTrue(user.getOwnedPlants().isEmpty());
}
I tested this method manually and I could see that it works correctly - changes to the database were made the way that I wanted. So why does the test fail? How should I go about writing it?
Solution
When you execute this row
userRepository.deletePlantById(1, 5);
you are deleting the user plants in the database, but the object user
has still the list of user plants inside.
In order to check that the deletion has been done correctly, you have to execute a query to find the user plants by the user id. I assume the interface UserPlantRepository
exists.
@Test
void givenPlantIdAndUserIdShouldDeletePlantOfThatIdFromUserPlants() {
userRepository.deletePlantById(1, 5);
assertTrue(userPlantRepository.findByUserId(1)).isEmpty()
}
Answered By - frascu
Answer Checked By - Katrina (JavaFixing Volunteer)