-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Closed
Labels
status: invalidAn issue that we don't feel is validAn issue that we don't feel is valid
Description
I'm learning Spring Boot as I go, and everything has been fine so far using Spring JPA to manage the database until I tried deleting an entity with an embedded key. See the attached project.
test-stability-api.zip
The relevant entity is as follows:
```@Setter
@Getter
@Data
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
@Cacheable
@ToString
@Builder
@Table(name = "test_case_execution_result")
@NamedQueries({
@NamedQuery(
name = "TestCaseExecutionResult.findAll",
query = "SELECT t FROM TestCaseExecutionResult t"),
@NamedQuery(
name = "TestCaseExecutionResult.findById",
query = "SELECT t FROM TestCaseExecutionResult t WHERE t.testCaseExecutionResultPK.id = :id"),
@NamedQuery(
name = "TestCaseExecutionResult.findByTestCaseResultId",
query =
"SELECT t FROM TestCaseExecutionResult t WHERE"
\+ " t.testCaseExecutionResultPK.testCaseResultId = :testCaseResultId"),
@NamedQuery(
name = "TestCaseExecutionResult.findByTestCaseId",
query =
"SELECT t FROM TestCaseExecutionResult t WHERE t.testCaseExecutionResultPK.testCaseId ="
\+ " :testCaseId"),
@NamedQuery(
name = "TestCaseExecutionResult.findByTestRegionId",
query =
"SELECT t FROM TestCaseExecutionResult t WHERE t.testCaseExecutionResultPK.testRegionId ="
\+ " :testRegionId"),
@NamedQuery(
name = "TestCaseExecutionResult.findByDate",
query = "SELECT t FROM TestCaseExecutionResult t WHERE t.date = :date"),
@NamedQuery(
name = "TestCaseExecutionResult.findByRelatedJob",
query = "SELECT t FROM TestCaseExecutionResult t WHERE t.relatedJob = :relatedJob")
})
public class TestCaseExecutionResult implements Serializable {
@Serial private static final long serialVersionUID = 1L;
@EmbeddedId protected TestCaseExecutionResultPK testCaseExecutionResultPK;
@Basic(optional = false)
@NotNull @Column(name = "date")
@Temporal(TemporalType.TIMESTAMP)
private Date date;
@Basic(optional = false)
@NotNull @Size(min = 1, max = 255)
@Column(name = "relatedJob")
private String relatedJob;
@JoinColumn(
name = "test_case_id",
referencedColumnName = "id",
insertable = false,
updatable = false)
@ManyToOne(optional = false)
private TestCase testCase;
@JoinColumn(
name = "test_case_result_id",
referencedColumnName = "id",
insertable = false,
updatable = false)
@ManyToOne(optional = false)
private TestCaseResult testCaseResult;
@JoinColumn(
name = "test_region_id",
referencedColumnName = "id",
insertable = false,
updatable = false)
@ManyToOne(optional = false)
private TestRegion testRegion;
public TestCaseExecutionResult(TestCaseExecutionResultPK testCaseExecutionResultPK) {
this.testCaseExecutionResultPK = testCaseExecutionResultPK;
}
public TestCaseExecutionResult(
TestCaseExecutionResultPK testCaseExecutionResultPK, Date date, String relatedJob) {
this.testCaseExecutionResultPK = testCaseExecutionResultPK;
this.date = date;
this.relatedJob = relatedJob;
}
public TestCaseExecutionResult(
int testCaseExecutionResultPK, int testCaseResultId, int testCaseId, int testRegionId) {
this.testCaseExecutionResultPK =
new TestCaseExecutionResultPK(
testCaseExecutionResultPK, testCaseResultId, testCaseId, testRegionId);
}
@Override
public int hashCode() {
int hash = 0;
hash += (testCaseExecutionResultPK != null ? testCaseExecutionResultPK.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof TestCaseExecutionResult other)) {
return false;
}
return (this.testCaseExecutionResultPK != null || other.testCaseExecutionResultPK == null)
&& (this.testCaseExecutionResultPK == null
|| this.testCaseExecutionResultPK.equals(other.testCaseExecutionResultPK));
}
}
This is the relevant controller:
```@RestController
@SuppressWarnings("PMD.TestClassWithoutTestCases")
public class TestCaseExecutionResultController {
private final TestCaseExecutionResultRepository repository;
private final TestCaseExecutionResultAssembler assembler;
public TestCaseExecutionResultController(
TestCaseExecutionResultRepository repository, TestCaseExecutionResultAssembler assembler) {
this.repository = repository;
this.assembler = assembler;
}
@PostMapping(Endpoints.EXECUTION_RESULT_REGION)
@ResponseStatus(HttpStatus.CREATED)
public ResponseEntity\<EntityModel\<TestCaseExecutionResult\>\> createTestCaseExecutionResult(
@RequestBody TestCaseExecutionResult testCaseExecutionResult,
@PathVariable Integer tcId,
@PathVariable Integer regionId,
@PathVariable Integer resultId) {
if (testCaseExecutionResult.getTestCaseExecutionResultPK() == null) {
testCaseExecutionResult.setTestCaseExecutionResultPK(
TestCaseExecutionResultPK.builder()
.testCaseResultId(resultId)
.testCaseId(tcId)
.testRegionId(regionId)
.build());
}
testCaseExecutionResult.setDate(new Date());
return ResponseEntity.ok(this.assembler.toModel(this.repository.save(testCaseExecutionResult)));
}
@GetMapping(Endpoints.EXECUTION_RESULTS)
public ResponseEntity\<CollectionModel\<EntityModel\<TestCaseExecutionResult\>\>\> findAll() {
return ResponseEntity.ok(this.assembler.toCollectionModel(this.repository.findAll()));
}
@GetMapping(Endpoints.EXECUTION_RESULTS_REGION)
public ResponseEntity\<CollectionModel\<EntityModel\<TestCaseExecutionResult\>\>\>
executionResultsForTestCaseInRegion(
@PathVariable Integer tcId, @PathVariable Integer regionId) throws NotFoundException {
return ResponseEntity.ok(
this.assembler.toCollectionModel(
this.repository.findByTestCaseIdAndTestRegionId(tcId, regionId)));
}
@DeleteMapping(Endpoints.EXECUTION_RESULT_REGION_EXECUTION)
public ResponseEntity\<?\> delete(
@PathVariable Integer tcId,
@PathVariable Integer regionId,
@PathVariable Integer resultId,
@PathVariable Integer executionId)
throws NotFoundException {
Iterable\<TestCaseExecutionResult\> results =
repository.findAllById(
List.of(new TestCaseExecutionResultPK(executionId, resultId, tcId, regionId)));
if (results.iterator().hasNext()) {
TestCaseExecutionResult target = results.iterator().next();
this.repository.deleteById(target.getTestCaseExecutionResultPK());
return ResponseEntity.noContent().build();
} else {
throw new NotFoundException(
"Test case execution result with id "
\+ new TestCaseExecutionResultPK(executionId, resultId, tcId, regionId)
\+ " not found");
}
}
}
Have the following test where I basically create the necesary entities and then create a test case execution result which works fine. Then I proceed to delete it but fail when I expect to no longer being able to find it via the API. This is the approach that I use in all the other tests and seem to work fine in those cases. The only difference I can find so far is the key for this entity.
```@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Slf4j
public class TestCaseExecutionTest {
@Autowired private TestCaseExecutionResultController controller;
@Autowired TestCaseExecutionResultRepository repository;
@Autowired private TestRegionRepository regionRepository;
@Autowired private TestCaseResultRepository resultRepository;
@Autowired private TestCaseRepository testCaseRepository;
@LocalServerPort private int port;
@Autowired private TestRestTemplate restTemplate;
@Test
void contextLoads() {
assertThat(controller).isNotNull();
}
@Test
@SneakyThrows
public void testCreateTestCaseExecutionResult() {
TestCase tc =
TestCase.builder()
.className("ClassName")
.testName("testName")
.testMethod("testMethod")
.description("description")
.build();
TestCase testCase = testCaseRepository.save(tc);
Iterator<TestRegion> iterator = regionRepository.findAll().iterator();
TestRegion region;
if (iterator.hasNext()) {
region = iterator.next();
} else {
region = TestRegion.builder().regionName(UUID.randomUUID().toString()).build();
regionRepository.save(region);
}
TestCaseResult testCaseResult = resultRepository.findById(1);
// Add an execution result
TestCaseExecutionResult request =
TestCaseExecutionResult.builder()
.testRegion(TestRegion.builder().id(region.getId()).build())
.testCase(TestCase.builder().id(testCase.getId()).build())
.testCaseResult(TestCaseResult.builder().id(testCaseResult.getId()).build())
.relatedJob("Dummy URL")
.build();
this.restTemplate.getForEntity(
"http://localhost:" + port + Endpoints.EXECUTION_RESULTS_REGION,
TestCaseExecutionResult.class,
request.getTestCase().getId(),
request.getTestRegion().getId());
assertTrue(Objects.requireNonNull(controller.findAll().getBody()).getContent().isEmpty());
TestCaseExecutionResult testCaseExecutionResult =
this.restTemplate.postForObject(
"http://localhost:" + port + Endpoints.EXECUTION_RESULT_REGION,
request,
TestCaseExecutionResult.class,
request.getTestCase().getId(),
request.getTestRegion().getId(),
request.getTestCaseResult().getId());
assertThat(testCaseExecutionResult).isNotNull();
assertThat(testCaseExecutionResult)
.usingRecursiveComparison()
.ignoringFields(
"testCaseExecutionResultPK", "date", "testCase", "testCaseResult", "testRegion")
.isEqualTo(request);
assertFalse(Objects.requireNonNull(controller.findAll().getBody()).getContent().isEmpty());
assertFalse(
Objects.requireNonNull(
controller
.executionResultsForTestCaseInRegion(
testCaseExecutionResult.getTestCase().getId(),
testCaseExecutionResult.getTestRegion().getId())
.getBody())
.getContent()
.isEmpty());
ResponseEntity<TestCaseExecutionResultWrapper> response =
this.restTemplate.getForEntity(
"http://localhost:" + port + Endpoints.EXECUTION_RESULTS_REGION,
TestCaseExecutionResultWrapper.class,
request.getTestCase().getId(),
request.getTestRegion().getId());
TestCaseExecutionResultWrapper wrapper = response.getBody();
assertNotNull(wrapper);
List<TestCaseExecutionResult> results = wrapper.getEmbedded().getTestCaseExecutionResults();
assertNotNull(results);
assertEquals(results.size(), 1);
testCaseExecutionResult = results.get(0);
// Delete it
this.restTemplate.delete(
"http://localhost:" + port + Endpoints.EXECUTION_RESULT_REGION_EXECUTION,
testCaseExecutionResult.getTestCaseExecutionResultPK().getTestCaseId(),
testCaseExecutionResult.getTestCaseExecutionResultPK().getTestRegionId(),
testCaseExecutionResult.getTestCaseExecutionResultPK().getTestCaseResultId(),
testCaseExecutionResult.getTestCaseExecutionResultPK().getId());
response =
this.restTemplate.getForEntity(
"http://localhost:" + port + Endpoints.EXECUTION_RESULTS_REGION,
TestCaseExecutionResultWrapper.class,
request.getTestCase().getId(),
request.getTestRegion().getId());
wrapper = response.getBody();
assertNotNull(wrapper);
results = wrapper.getEmbedded().getTestCaseExecutionResults();
assertNotNull(results);
if (!results.isEmpty()) {
ObjectMapper objectMapper = new ObjectMapper();
repository
.findAll()
.iterator()
.forEachRemaining(
item -> {
try {
String json =
objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(item);
log.info(json);
} catch (JsonProcessingException e) {
log.error("Error converting item to JSON", e);
}
});
}
assertEquals(results.size(), 0);
}
}
I was expecting the deleted entity not to be found afterward.
Metadata
Metadata
Assignees
Labels
status: invalidAn issue that we don't feel is validAn issue that we don't feel is valid