Spring Data JPA repositories backed by HashMap (alternative for mocks).
If you dont want to use Testcontainers or H2 database, its worth to considering in-memory repository instead of mocks.
- CrudRepository (fully supported)
- PagingAndSortingRepository (fully supported)
- JpaRepository (queries by Example not implemented)
- to write tests, we dont have to investigate how service use repository
- service can be tested as blackbox
- give input and verify output
- refactor with ease
- entity must have ID field annotated with
@Id
Simple Spring Boot app:
@Service
class BookService {
private final BookRepository bookRepository;
@Autowired
BookService(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
}
@Repository
interface BookRepository extends JpaRepository<BookEntity, Long> {
}
@Entity
public final class BookEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
//...
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BookEntity that = (BookEntity) o;
return Objects.equals(id, that.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
How to test BookService using in-memory repository?
- Create new repository class, that
- extends one of three available repositories:
InMemoryJpaRepository
orInMemoryCrudRepository
orInMemoryPagingAndSortingRepository
. In this case we useInMemoryJpaRepository
- implements entity`s repository interface
- extends one of three available repositories:
class InMemoryBookRepository extends InMemoryJpaRepository<BookEntity, Long> implements BookRepository {
public InMemoryBookRepository() {
super(1L, IdGenerators.IncrementalLongIdGenerator);
}
}
- Pass instance of this class to service: BookServiceTest.java
public class BookServiceTest {
BookService bookService = new BookService(new InMemoryBookRepository());
@Test
public test() {
//...
}
}
- Everything is ready to write tests
Check out entire code of this example: