InMemoryJpaRepository.java

1
package com.reallifedeveloper.tools.test.database.inmemory;
2
3
import java.lang.reflect.Field;
4
import java.lang.reflect.Method;
5
import java.util.List;
6
import java.util.Optional;
7
import java.util.function.Function;
8
9
import org.springframework.dao.IncorrectResultSizeDataAccessException;
10
import org.springframework.data.domain.Example;
11
import org.springframework.data.domain.Page;
12
import org.springframework.data.domain.Pageable;
13
import org.springframework.data.domain.Sort;
14
import org.springframework.data.jpa.domain.DeleteSpecification;
15
import org.springframework.data.jpa.domain.PredicateSpecification;
16
import org.springframework.data.jpa.domain.Specification;
17
import org.springframework.data.jpa.domain.UpdateSpecification;
18
import org.springframework.data.jpa.repository.JpaRepository;
19
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
20
import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery;
21
22
import jakarta.persistence.EmbeddedId;
23
import jakarta.persistence.EntityNotFoundException;
24
import jakarta.persistence.Id;
25
import jakarta.persistence.IdClass;
26
27
/**
28
 * An implementation of the Spring Data JPA {@code JpaRepository} interface that holds entities in a map. Useful for testing.
29
 *
30
 * @param <T>  the type of the entities handled by this repository
31
 * @param <ID> the type of the entities' primary keys
32
 *
33
 * @author RealLifeDeveloper
34
 */
35
@SuppressWarnings({ "PMD.CouplingBetweenObjects", "PMD.TooManyMethods" })
36
public class InMemoryJpaRepository<T, ID extends Comparable<? super ID>> extends AbstractInMemoryCrudRepository<T, ID>
37
        implements JpaRepository<T, ID>, JpaSpecificationExecutor<T> {
38
39
    private final PredicateSpecificationEvaluator<T> predicateSpecificationEvaluator = new PredicateSpecificationEvaluator<>();
40
41
    /**
42
     * Creates a new {@code InMemoryJpaRepository} with no primary key generator. If an entity with a {@code null} primary key is saved, an
43
     * exception is thrown.
44
     */
45
    public InMemoryJpaRepository() {
46
        super();
47
    }
48
49
    /**
50
     * Creates a new {@code InMemoryJpaRepository} with the provided primary key generator. If an entity with a {@code null} primary key is
51
     * saved, the generator is used to create a new primary key that is stored in the entity before saving.
52
     *
53
     * @param primaryKeyGenerator the primary key generator to use
54
     */
55
    public InMemoryJpaRepository(PrimaryKeyGenerator<ID> primaryKeyGenerator) {
56
        super(primaryKeyGenerator);
57
    }
58
59
    /**
60
     * Gives the {@link PredicateSpecificationEvaluator} used by this repository. This is useful for registering functions used by
61
     * {@code PredicateSpecifications}, and could occasionally be useful to directly check if a predicate specification matches an entity.
62
     *
63
     * @return the {@code PredicateSpecificationEvaluator} used by this repository.
64
     */
65
    public PredicateSpecificationEvaluator<T> predicateSpecificationEvaluator() {
66 1 1. predicateSpecificationEvaluator : replaced return value with null for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::predicateSpecificationEvaluator → KILLED
        return predicateSpecificationEvaluator;
67
    }
68
69
    /**
70
     * {@inheritDoc}
71
     */
72
    @Override
73
    public void deleteAllInBatch() {
74 1 1. deleteAllInBatch : removed call to com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::deleteAll → KILLED
        deleteAll();
75
    }
76
77
    /**
78
     * {@inheritDoc}
79
     */
80
    @Override
81
    public void deleteAllInBatch(Iterable<T> entities) {
82 1 1. deleteAllInBatch : removed call to com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::deleteAll → KILLED
        deleteAll(entities);
83
    }
84
85
    /**
86
     * {@inheritDoc}
87
     */
88
    @Override
89
    public void deleteAllByIdInBatch(Iterable<ID> ids) {
90 1 1. deleteAllByIdInBatch : removed call to com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::deleteAllById → KILLED
        deleteAllById(ids);
91
    }
92
93
    /**
94
     * {@inheritDoc}
95
     */
96
    @Override
97
    public void flush() {
98
        // Do nothing.
99
    }
100
101
    /**
102
     * {@inheritDoc}
103
     */
104
    @Override
105
    public <S extends T> S saveAndFlush(S entity) {
106
        S savedEntity = save(entity);
107 1 1. saveAndFlush : removed call to com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::flush → SURVIVED
        flush();
108 1 1. saveAndFlush : replaced return value with null for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::saveAndFlush → SURVIVED
        return savedEntity;
109
    }
110
111
    /**
112
     * {@inheritDoc}
113
     */
114
    @Override
115
    public <S extends T> List<S> saveAllAndFlush(Iterable<S> entities) {
116
        List<S> savedEntities = saveAll(entities);
117 1 1. saveAllAndFlush : removed call to com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::flush → SURVIVED
        flush();
118 1 1. saveAllAndFlush : replaced return value with Collections.emptyList for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::saveAllAndFlush → SURVIVED
        return savedEntities;
119
    }
120
121
    /**
122
     * {@inheritDoc}
123
     */
124
    @Override
125
    @SuppressWarnings("deprecation")
126
    public T getById(ID id) {
127
        Optional<T> optionalElement = findById(id);
128 2 1. lambda$getById$0 : replaced return value with null for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::lambda$getById$0 → KILLED
2. getById : replaced return value with null for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::getById → KILLED
        return optionalElement.orElseThrow(() -> new EntityNotFoundException("Entity with ID " + id + " not found"));
129
    }
130
131
    /**
132
     * {@inheritDoc}
133
     */
134
    @Override
135
    @SuppressWarnings("deprecation")
136
    public T getOne(ID id) {
137 1 1. getOne : replaced return value with null for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::getOne → KILLED
        return getById(id);
138
    }
139
140
    @Override
141
    protected boolean isIdField(Field field) {
142 3 1. isIdField : negated conditional → KILLED
2. isIdField : replaced boolean return with true for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::isIdField → KILLED
3. isIdField : negated conditional → KILLED
        return field.getAnnotation(Id.class) != null || field.getAnnotation(EmbeddedId.class) != null;
143
    }
144
145
    @Override
146
    protected boolean isIdMethod(Method method) {
147 3 1. isIdMethod : replaced boolean return with true for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::isIdMethod → KILLED
2. isIdMethod : negated conditional → KILLED
3. isIdMethod : negated conditional → KILLED
        return method.getAnnotation(Id.class) != null || method.getAnnotation(EmbeddedId.class) != null;
148
    }
149
150
    @Override
151
    @SuppressWarnings("unchecked")
152
    protected Optional<Class<ID>> getCompositeIdClass(Object entity) {
153
        IdClass idClass = entity.getClass().getAnnotation(IdClass.class);
154 1 1. getCompositeIdClass : negated conditional → KILLED
        if (idClass == null) {
155
            return Optional.empty();
156
        } else {
157 1 1. getCompositeIdClass : replaced return value with Optional.empty for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::getCompositeIdClass → KILLED
            return Optional.ofNullable((Class<ID>) idClass.value());
158
        }
159
    }
160
161
    @Override
162
    public <S extends T, R> R findBy(Example<S> example, Function<FetchableFluentQuery<S>, R> queryFunction) {
163
        throw new UnsupportedOperationException("findBy(Example, Function<FetchableFluentQuery, R>)");
164
    }
165
166
    @Override
167
    public T getReferenceById(ID id) {
168
        throw new UnsupportedOperationException("getReferenceById(ID)");
169
    }
170
171
    //
172
    // JpaSpecificationExecutor methods
173
    //
174
175
    @Override
176
    public long count(PredicateSpecification<T> spec) {
177 1 1. count : replaced long return with 0 for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::count → KILLED
        return findAll(spec).size();
178
    }
179
180
    @Override
181
    public long delete(PredicateSpecification<T> spec) {
182
        List<T> toDelete = findAll(spec);
183 1 1. delete : removed call to com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::deleteAll → KILLED
        deleteAll(toDelete);
184 1 1. delete : replaced long return with 0 for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::delete → SURVIVED
        return toDelete.size();
185
    }
186
187
    @Override
188
    public boolean exists(PredicateSpecification<T> spec) {
189 2 1. exists : negated conditional → KILLED
2. exists : replaced boolean return with true for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::exists → KILLED
        return !findAll(spec).isEmpty();
190
    }
191
192
    @Override
193
    public List<T> findAll(PredicateSpecification<T> spec) {
194 1 1. findAll : replaced return value with Collections.emptyList for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::findAll → KILLED
        return predicateSpecificationEvaluator.filter(spec, findAll());
195
    }
196
197
    @Override
198
    public <S extends T, R> R findBy(PredicateSpecification<T> spec, Function<? super SpecificationFluentQuery<S>, R> queryFunction) {
199
        throw new UnsupportedOperationException("findBy(PredicateSpecification, Function<SpecificationFluentQuery, R>)");
200
    }
201
202
    @Override
203
    public Optional<T> findOne(PredicateSpecification<T> spec) {
204
        List<T> found = findAll(spec);
205 1 1. findOne : negated conditional → KILLED
        if (found.isEmpty()) {
206
            return Optional.empty();
207 1 1. findOne : negated conditional → KILLED
        } else if (found.size() == 1) {
208 1 1. findOne : replaced return value with Optional.empty for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::findOne → KILLED
            return Optional.of(found.getFirst());
209
        } else {
210
            throw new IncorrectResultSizeDataAccessException(1, found.size());
211
        }
212
    }
213
214
    @Override
215
    public long delete(DeleteSpecification<T> spec) {
216
        throw new UnsupportedOperationException("delete(DeleteSpecification)");
217
    }
218
219
    @Override
220
    public long count(Specification<T> spec) {
221
        throw new UnsupportedOperationException("count(Specification)");
222
    }
223
224
    @Override
225
    public boolean exists(Specification<T> spec) {
226
        throw new UnsupportedOperationException("exists(Specification)");
227
    }
228
229
    @Override
230
    public List<T> findAll(Specification<T> spec) {
231
        throw new UnsupportedOperationException("findAll(Specification)");
232
    }
233
234
    @Override
235
    public Page<T> findAll(Specification<T> spec, Pageable pageable) {
236
        throw new UnsupportedOperationException("findAll(Specification, Pageable)");
237
    }
238
239
    @Override
240
    public List<T> findAll(Specification<T> spec, Sort sort) {
241
        throw new UnsupportedOperationException("findAll(Specification, Sort)");
242
    }
243
244
    @Override
245
    public Page<T> findAll(Specification<T> spec, Specification<T> countSpec, Pageable pageable) {
246
        throw new UnsupportedOperationException("findAll(Specification, Specification, Pageable)");
247
    }
248
249
    @Override
250
    public <S extends T, R> R findBy(Specification<T> spec, Function<? super SpecificationFluentQuery<S>, R> queryFunction) {
251
        throw new UnsupportedOperationException("findBy(Specification, Function<SpecificationFluentQuery, R>)");
252
    }
253
254
    @Override
255
    public Optional<T> findOne(Specification<T> spec) {
256
        throw new UnsupportedOperationException("findOne(Specification)");
257
    }
258
259
    @Override
260
    public long update(UpdateSpecification<T> spec) {
261
        throw new UnsupportedOperationException("update(UpdateSpecification)");
262
    }
263
264
}

Mutations

66

1.1
Location : predicateSpecificationEvaluator
Killed by : com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest]/[method:predicateSpecificationEvaluatorIsNotNull()]
replaced return value with null for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::predicateSpecificationEvaluator → KILLED

74

1.1
Location : deleteAllInBatch
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:deleteAllInBatch()]
removed call to com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::deleteAll → KILLED

82

1.1
Location : deleteAllInBatch
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:deleteNullEntitiesInBatch()]
removed call to com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::deleteAll → KILLED

90

1.1
Location : deleteAllByIdInBatch
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:deleteAllByIdInBatch()]
removed call to com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::deleteAllById → KILLED

107

1.1
Location : saveAndFlush
Killed by : none
removed call to com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::flush → SURVIVED
Covering tests

108

1.1
Location : saveAndFlush
Killed by : none
replaced return value with null for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::saveAndFlush → SURVIVED
Covering tests

117

1.1
Location : saveAllAndFlush
Killed by : none
removed call to com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::flush → SURVIVED
Covering tests

118

1.1
Location : saveAllAndFlush
Killed by : none
replaced return value with Collections.emptyList for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::saveAllAndFlush → SURVIVED
Covering tests

128

1.1
Location : lambda$getById$0
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:getByIdEmpty()]
replaced return value with null for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::lambda$getById$0 → KILLED

2.2
Location : getById
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:mappedSuperclassWithFieldAnnotations()]
replaced return value with null for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::getById → KILLED

137

1.1
Location : getOne
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:getOne()]
replaced return value with null for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::getOne → KILLED

142

1.1
Location : isIdField
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:deleteEntityWithNullId()]
negated conditional → KILLED

2.2
Location : isIdField
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:deleteEntityWithNullId()]
replaced boolean return with true for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::isIdField → KILLED

3.3
Location : isIdField
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:deleteEntityWithNullId()]
negated conditional → KILLED

147

1.1
Location : isIdMethod
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:entityWithNoIdAnnotation()]
replaced boolean return with true for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::isIdMethod → KILLED

2.2
Location : isIdMethod
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:entityWithNoIdAnnotation()]
negated conditional → KILLED

3.3
Location : isIdMethod
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:entityWithNoIdAnnotation()]
negated conditional → KILLED

154

1.1
Location : getCompositeIdClass
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:deleteEntityWithNullId()]
negated conditional → KILLED

157

1.1
Location : getCompositeIdClass
Killed by : com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.InMemoryJpaRepositoryTest]/[method:idClassSaveWithPrimaryKeys()]
replaced return value with Optional.empty for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::getCompositeIdClass → KILLED

177

1.1
Location : count
Killed by : com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest]/[method:count()]
replaced long return with 0 for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::count → KILLED

183

1.1
Location : delete
Killed by : com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest]/[method:delete()]
removed call to com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::deleteAll → KILLED

184

1.1
Location : delete
Killed by : none
replaced long return with 0 for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::delete → SURVIVED
Covering tests

189

1.1
Location : exists
Killed by : com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest]/[method:exists()]
negated conditional → KILLED

2.2
Location : exists
Killed by : com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest]/[method:exists()]
replaced boolean return with true for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::exists → KILLED

194

1.1
Location : findAll
Killed by : com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest]/[method:findAll()]
replaced return value with Collections.emptyList for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::findAll → KILLED

205

1.1
Location : findOne
Killed by : com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest]/[method:findOneReturnsEmptyOptionalIfNothingFound()]
negated conditional → KILLED

207

1.1
Location : findOne
Killed by : com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest]/[method:findOne()]
negated conditional → KILLED

208

1.1
Location : findOne
Killed by : com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest.[engine:junit-jupiter]/[class:com.reallifedeveloper.tools.test.database.inmemory.JpaSpecificationExecutorTest]/[method:findOne()]
replaced return value with Optional.empty for com/reallifedeveloper/tools/test/database/inmemory/InMemoryJpaRepository::findOne → KILLED

Active mutators

Tests examined


Report generated by PIT 1.25.9 support