Search code examples
javaspring-bootjunit

JUnit5 repository class test cases


This my JUni5 repository levele test cases

@DataJpaTest
@ExtendWith(MockitoExtension.class)
@AutoConfigureTestDatabase(replace = Replace.NONE)
class WalletRepositoryTest {
    @Mock private WalletRepository walletRepository;
    @Mock private UserRepository userRepository;
    private static final User USER = createUser();
    private static final WalletDetail WALLET_DETAIL = createWalletDetail(USER);

    private static User createUser() {
        final var user = new User();
        user.setUserId(1);
        user.setUid("4dcd810b-b9b1-4006-89a2-b50e9ed5ee67");
        user.setName("guest");
        user.setMobileNo("1234567890");
        user.setEmail("guest98787@guest.com");
        user.setPassword("1234abc");
        return user;
    }

    private static WalletDetail createWalletDetail(final User user) {
        final var walletDetail = new WalletDetail();
        walletDetail.setWalletId(1);
        walletDetail.setUid("86bd3f49-f9bc-425c-b5a1-2f353e9061ff");
        walletDetail.setUser(user);
        walletDetail.setWalletAmount(20.0);
        return walletDetail;
    }
    @Test
    void findByUser() {
        when(userRepository.save(any(User.class))).thenReturn(USER);
        when(walletRepository.save(any(WalletDetail.class))).thenReturn(WALLET_DETAIL);
        when(walletRepository.findByUser(anyInt())).thenReturn(WALLET_DETAIL);

        userRepository.save(USER);
        walletRepository.save(WALLET_DETAIL);

        final var result = walletRepository.findByUser(1);

        assertNotNull(result);
        assertEquals(1, result.getWalletId());
    }
}

in my project, I am using Gradle And using PostgreSQL database

when in my system closes the database connection my test cases not working when I create a build.

show this error

WalletRepositoryTest > findByUser() FAILED
    java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:142
        Caused by: org.springframework.beans.factory.BeanCreationException at AbstractAutowireCapableBeanFactory.java:1762
            Caused by: org.flywaydb.core.internal.exception.FlywaySqlException at JdbcUtils.java:60
                Caused by: org.postgresql.util.PSQLException at ConnectionFactoryImpl.java:342
                    Caused by: java.net.ConnectException at Net.java:-2

So my question is when do we really need a database connection for test cases?

and how do we write JUnit 5 test cases without a database connection


Solution

  • You can use an in-memory database if you want to avoid mocking the repository. This will give you more flexibility (for instance, the test will not care if you call saveWallet 3 times or saveAllWallets(...) once). On the other hand, the mocks will make the test run much faster, so it's basically a trade-off.

    In your case, you have to decide if you want to use a @DataJpaTest and the in-memory database. This will mean you need to set up the DB connection as explained in this article. To test, you will then use @Autowire for the repositories instead of trying to mock them.

    Alternatively, you can use @Mock or @MockBean for the repositories and do not set up an in-memory DB (and no longer user @DataJpaTest).

    Lastly, you should avoid mocking the class you want to test. So, if you want to test a WalletService that uses WaleltRepo, you can mock WalletRepo. But if you want to test WalletRepo that talks to the DB, you'll need to "mock" the DB by providing this in-memory solution