Create HibernateUserRepositoryTests

In HibernateUserRepositoryTests, we will create the following test methods to cover different scenarios:

  • save_nullUsernameUser_shouldFail()
  • save_nullEmailAddressUser_shouldFail()
  • save_nullPasswordUser_shouldFail()
  • save_validUser_shouldSuccess()
  • save_usernameAlreadyExist_shouldFail()
  • save_emailAddressAlreadyExist_shouldFail()
  • findByEmailAddress_notExist_shouldReturnEmptyResult()
  • findByEmailAddress_exist_shouldReturnResult()
  • findByUsername_notExist_shouldReturnEmptyResult()
  • findByUsername_exist_shouldReturnResult()

First of all, let's add a H2 dependency into Maven's pom.xml as follows, so that when Spring Boot starts the tests, it knows that we need H2 instead of MySQL:

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>

Since the data source configuration that H2 requires is different from the one that MySQL uses in src/main/resources/application.properties, let's create application.properties in the src/test/resources/ directory with the following settings for H2:

spring.datasource.url=jdbc:h2:mem:taskagile;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE 
spring.datasource.username=sa
spring.datasource.password=sa
spring.datasource.driver-class-name=org.h2.Driver

spring.jpa.open-in-view=false
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

As you can see, we use the H2 database by specifying url and driver-class-name of the data source, and let Hibernate autogenerate and drop the database by specifying ddl-auto to create-drop. We also turn off Hibernate's Open Session In View feature, and then we let JPA know the database platform we're using through the class name of Hibernate's H2Dialect.

Since we've added the spring.jpa.* settings in src/test/resources/application.properties, let's also add the following settings into src/main/resources.application.properties to make it clear that we need these settings for the environments other than test:

spring.jpa.open-in-view=false
spring.jpa.hibernate.ddl-auto=none
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect

It is only when Spring is run in the test profile that it will read the settings in the src/test/resources/application.properties file. By default, when you start the Sprint Boot application, it runs in the dev profile. We will need to change the active profile so that Spring can know we're doing testing. We can apply the @ActiveProfiles annotation to tests, such as the following TaskAgileApplicationTests, which is initially generated by Spring Initializr:

...
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("test")
public class TaskAgileApplicationTests {
@Test
public void contextLoads() {
}
}

As you can see, we use the @SpringBootTest annotation here so that Spring Boot will look for a main class, in our case, the TaskAgileApplication class, which is annotated with @SpringBootApplication, and then start a Spring application context with all of the Spring beans defined in the application loaded into the context. Without specifying the profile by using the @ActiveProfiles annotation, when we run the mvn clean install command, or mvn test, Spring will read src/main/resources/application.properties for the dev profile and won't be able to initialize the H2 database.

Another property file that we need to add is src/test/resources/hibernate.properties, which looks like the following:

hibernate.hbm2ddl.auto=create-drop
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.show_sql=true
hibernate.format_sql=true

During the test, Hibernate will pick up the settings from this file.

Now, let's get back to HibernateUserRepositoryTests.  The following is the first test method:

...
@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@DataJpaTest
public class HibernateUserRepositoryTests {

@TestConfiguration
public static class UserRepositoryTestContextConfiguration {
@Bean
public UserRepository userRepository(EntityManager entityManager) {
return new HibernateUserRepository(entityManager);
}
}

@Autowired
private UserRepository repository;

@Test(expected = PersistenceException.class)
public void save_nullUsernameUser_shouldFail() {
User inavlidUser = User.create(
null, "[email protected]", "MyPassword!");
repository.save(inavlidUser);
}
}

As you can see, we apply the @ActiveProfiles annotation to it as well as the @DataJpaTest annotation. Unlike the @SpringBootTest annotation, the @DataJpaTest annotation is only for testing JPA components. With its presence, by default, tests will use an embedded in-memory database, in our case, the H2 database. We create an inner configuration class to create an instance of HibernateUserRepository so that it can be auto-wired into the test class.

In fact, if we used UserRepository the Spring Data JPA way, we wouldn't need to instantiate UserRepository like this using a test configuration, because Spring will generate the repository implementation and instantiate it for us automatically with the presence of the @DataJpaTest annotation.

In this test, we don't need to create any mocks. All of the database interactions will be performed against the in-memory database.

In the save_nullUsernameUser_shouldFail() method, we try to save a user without username, and it should fail because, in the User entity, we put nullable=false in the @Column annotation that applied to the username field.

We will not go through the rest of the test methods here because the only major difference that this HibernateUserRepositoryeTests has with all the previous tests we created is how the embedded database is initialized. You can find the details of this test class in the commit history on GitHub.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.91.254