Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Checks getter usage for generated id fields #893

Merged
merged 1 commit into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- Check that getters are used for all generated JPA id fields. ([Issue 892](https://github.com/jqno/equalsverifier/issues/892))

## [3.15.4] - 2023-11-29

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ private void assertEntity(
) {
assertTrue(
Formatter.of(
"JPA Entity: direct reference to field %% used in %% instead of getter %%.",
"JPA Entity: direct reference to field %% used in %% instead of getter %%().",
fieldName,
method,
getterName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,13 @@ public void postProcess(Set<Class<?>> types, AnnotationCache annotationCache) {
"javax.persistence.ManyToOne",
"javax.persistence.ManyToMany",
"javax.persistence.ElementCollection",
"javax.persistence.GeneratedValue",
"jakarta.persistence.OneToOne",
"jakarta.persistence.OneToMany",
"jakarta.persistence.ManyToOne",
"jakarta.persistence.ManyToMany",
"jakarta.persistence.ElementCollection"
"jakarta.persistence.ElementCollection",
"jakarta.persistence.GeneratedValue"
),

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
package nl.jqno.equalsverifier.integration.extra_features;

import jakarta.persistence.Basic;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.*;
import java.util.Arrays;
import java.util.Objects;
import nl.jqno.equalsverifier.EqualsVerifier;
Expand Down Expand Up @@ -53,7 +46,7 @@ public void basicGetterNotUsed_givenWarningSuppressed() {
}

@Test
public void basicGetterUsed_givenAnnotationIsOnGetter() {
public void basicGetterNotUsed_givenAnnotationIsOnGetter() {
getterNotUsed(IncorrectBasicJakartaLazyGetterContainer.class, "equals");
getterNotUsed_warningSuppressed(IncorrectBasicJakartaLazyGetterContainer.class);
}
Expand Down Expand Up @@ -148,17 +141,48 @@ public void differentCodingStyle_multiple() {
.verify();
}

private void getterNotUsed(Class<?> type, String method) {
@Test
public void getterUsedForGeneratedId() {
EqualsVerifier
.forClass(CorrectGeneratedJpaIdContainer.class)
.suppress(Warning.SURROGATE_KEY)
.verify();
EqualsVerifier
.forClass(CorrectGeneratedJpaIdContainer.class)
.suppress(Warning.SURROGATE_OR_BUSINESS_KEY)
.verify();
}

@Test
public void getterNotUsedForGeneratedId() {
getterNotUsed(IncorrectGeneratedJpaIdContainer.class, "equals", Warning.SURROGATE_KEY);
getterNotUsed_warningSuppressed(
IncorrectGeneratedJpaIdContainer.class,
Warning.SURROGATE_KEY
);
getterNotUsed(
IncorrectGeneratedJpaIdContainer.class,
"equals",
Warning.SURROGATE_OR_BUSINESS_KEY
);
getterNotUsed_warningSuppressed(
IncorrectGeneratedJpaIdContainer.class,
Warning.SURROGATE_OR_BUSINESS_KEY
);
}

private void getterNotUsed(Class<?> type, String method, Warning... additionalWarnings) {
ExpectedException
.when(() -> EqualsVerifier.forClass(type).suppress(Warning.NONFINAL_FIELDS).verify())
.when(() -> EqualsVerifier.forClass(type).suppress(additionalWarnings).verify())
.assertFailure()
.assertMessageContains("JPA Entity", method, "direct reference");
}

private void getterNotUsed_warningSuppressed(Class<?> type) {
private void getterNotUsed_warningSuppressed(Class<?> type, Warning... additionalWarnings) {
EqualsVerifier
.forClass(type)
.suppress(Warning.JPA_GETTER, Warning.NONFINAL_FIELDS)
.suppress(Warning.JPA_GETTER)
.suppress(additionalWarnings)
.verify();
}

Expand Down Expand Up @@ -612,4 +636,56 @@ public int hashCode() {
return Objects.hash(getOneToMany(), getManyToOne());
}
}

@Entity
static class CorrectGeneratedJpaIdContainer {

@Id
@GeneratedValue
private String id;

public String getId() {
return id;
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof CorrectGeneratedJpaIdContainer)) {
return false;
}
CorrectGeneratedJpaIdContainer other = (CorrectGeneratedJpaIdContainer) obj;
return Objects.equals(getId(), other.getId());
}

@Override
public int hashCode() {
return Objects.hash(getId());
}
}

@Entity
static class IncorrectGeneratedJpaIdContainer {

@Id
@GeneratedValue
private String id;

public String getId() {
return id;
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof IncorrectGeneratedJpaIdContainer)) {
return false;
}
IncorrectGeneratedJpaIdContainer other = (IncorrectGeneratedJpaIdContainer) obj;
return Objects.equals(id, other.id);
}

@Override
public int hashCode() {
return Objects.hash(getId());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,7 @@
import nl.jqno.equalsverifier.EqualsVerifier;
import nl.jqno.equalsverifier.Warning;
import nl.jqno.equalsverifier.internal.testhelpers.ExpectedException;
import nl.jqno.equalsverifier.testhelpers.annotations.javax.persistence.Basic;
import nl.jqno.equalsverifier.testhelpers.annotations.javax.persistence.ElementCollection;
import nl.jqno.equalsverifier.testhelpers.annotations.javax.persistence.Entity;
import nl.jqno.equalsverifier.testhelpers.annotations.javax.persistence.FetchType;
import nl.jqno.equalsverifier.testhelpers.annotations.javax.persistence.ManyToMany;
import nl.jqno.equalsverifier.testhelpers.annotations.javax.persistence.ManyToOne;
import nl.jqno.equalsverifier.testhelpers.annotations.javax.persistence.OneToMany;
import nl.jqno.equalsverifier.testhelpers.annotations.javax.persistence.OneToOne;
import nl.jqno.equalsverifier.testhelpers.annotations.javax.persistence.*;
import org.junit.jupiter.api.Test;

// CHECKSTYLE OFF: HiddenField
Expand Down Expand Up @@ -46,7 +39,7 @@ public void basicGetterNotUsed_givenWarningSuppressed() {
}

@Test
public void basicGetterUsed_givenAnnotationIsOnGetter() {
public void basicGetterNotUsed_givenAnnotationIsOnGetter() {
getterNotUsed(IncorrectBasicJpaLazyGetterContainer.class, "equals");
getterNotUsed_warningSuppressed(IncorrectBasicJpaLazyGetterContainer.class);
}
Expand Down Expand Up @@ -138,15 +131,49 @@ public void differentCodingStyle_multiple() {
.verify();
}

private void getterNotUsed(Class<?> type, String method) {
@Test
public void getterUsedForGeneratedId() {
EqualsVerifier
.forClass(CorrectGeneratedJpaIdContainer.class)
.suppress(Warning.SURROGATE_KEY)
.verify();
EqualsVerifier
.forClass(CorrectGeneratedJpaIdContainer.class)
.suppress(Warning.SURROGATE_OR_BUSINESS_KEY)
.verify();
}

@Test
public void getterNotUsedForGeneratedId() {
getterNotUsed(IncorrectGeneratedJpaIdContainer.class, "equals", Warning.SURROGATE_KEY);
getterNotUsed_warningSuppressed(
IncorrectGeneratedJpaIdContainer.class,
Warning.SURROGATE_KEY
);
getterNotUsed(
IncorrectGeneratedJpaIdContainer.class,
"equals",
Warning.SURROGATE_OR_BUSINESS_KEY
);
getterNotUsed_warningSuppressed(
IncorrectGeneratedJpaIdContainer.class,
Warning.SURROGATE_OR_BUSINESS_KEY
);
}

private void getterNotUsed(Class<?> type, String method, Warning... additionalWarnings) {
ExpectedException
.when(() -> EqualsVerifier.forClass(type).verify())
.when(() -> EqualsVerifier.forClass(type).suppress(additionalWarnings).verify())
.assertFailure()
.assertMessageContains("JPA Entity", method, "direct reference");
}

private void getterNotUsed_warningSuppressed(Class<?> type) {
EqualsVerifier.forClass(type).suppress(Warning.JPA_GETTER).verify();
private void getterNotUsed_warningSuppressed(Class<?> type, Warning... additionalWarnings) {
EqualsVerifier
.forClass(type)
.suppress(Warning.JPA_GETTER)
.suppress(additionalWarnings)
.verify();
}

@Entity
Expand Down Expand Up @@ -596,4 +623,56 @@ public int hashCode() {
return Objects.hash(getOneToMany(), getManyToOne());
}
}

@Entity
static class CorrectGeneratedJpaIdContainer {

@Id
@GeneratedValue
private String id;

public String getId() {
return id;
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof CorrectGeneratedJpaIdContainer)) {
return false;
}
CorrectGeneratedJpaIdContainer other = (CorrectGeneratedJpaIdContainer) obj;
return Objects.equals(getId(), other.getId());
}

@Override
public int hashCode() {
return Objects.hash(getId());
}
}

@Entity
static class IncorrectGeneratedJpaIdContainer {

@Id
@GeneratedValue
private String id;

public String getId() {
return id;
}

@Override
public boolean equals(Object obj) {
if (!(obj instanceof IncorrectGeneratedJpaIdContainer)) {
return false;
}
IncorrectGeneratedJpaIdContainer other = (IncorrectGeneratedJpaIdContainer) obj;
return Objects.equals(id, other.id);
}

@Override
public int hashCode() {
return Objects.hash(getId());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package nl.jqno.equalsverifier.testhelpers.annotations.javax.persistence;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface GeneratedValue {
}
Loading