首页 > 解决方案 > Java 实体类及其单元测试的良好实践

问题描述

我只是想确认你们是否认为这是一个好习惯:

@Builder
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@ToString(exclude = "client")
@Data
@Entity
@Table(name = "addresses")
public class Address extends BaseEntity {

  private static final long serialVersionUID = -5966581124342250987L;

  @NotNull
  @Size(min = 2, max = 40)
  @Column(name = "line1", nullable = false, length = 40)
  private String line1;

  @Size(min = 2, max = 40)
  @Column(name = "line2", length = 40)
  private String line2;

  @NotNull
  @Size(min = 2, max = 40)
  @Column(name = "city", length = 40)
  private String city;

  @NotNull
  @Size(min = 2, max = 2)
  @Column(name = "country_code", length = 2)
  private String countryCode; //code ISO 3166 two-letter country codes

  @NotNull
  @EqualsAndHashCode.Exclude
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "client_id")
  private Client client;

}

class AddressTest {

  private static final String ADDRESS_LINE1 = "Address line 1";
  private static final String ADDRESS_LINE2 = "Address line 2";
  private static final String ADDRESS_CITY = "Address City";
  private static final String ADDRESS_COUNTRY_CODE = "IT";
  private static final Client ADDRESS_CLIENT = new Client();

  private Address address;

  @BeforeEach
  void setUp() {
    address = Address.builder()
            .line1( ADDRESS_LINE1 )
            .line2( ADDRESS_LINE2 )
            .city( ADDRESS_CITY )
            .countryCode( ADDRESS_COUNTRY_CODE )
            .client( ADDRESS_CLIENT )
            .build();
  }

  @Test
  public void CreateAddress_AssertBasicFields() {
    assertEquals(ADDRESS_LINE1, address.getLine1());

    assertEquals(ADDRESS_LINE2, address.getLine2());

    assertEquals(ADDRESS_CITY, address.getCity());

    assertEquals(ADDRESS_COUNTRY_CODE, address.getCountryCode());
  }

  @Test
  public void CreateAddress_AssertClient() {
    assertEquals(ADDRESS_CLIENT, address.getClient());
  }
}
public class AddressValidationTest {
  private static ValidatorFactory validatorFactory;
  private static Validator validator;

  private static final String ADDRESS_LINE1 = "Address line 1";
  private static final String ADDRESS_LINE2 = "Address line 2";
  private static final String ADDRESS_CITY = "Address City";
  private static final String ADDRESS_COUNTRY_CODE = "IT";
  private static final Client ADDRESS_CLIENT = new Client();

  @BeforeAll
  public static void createValidator() {
    validatorFactory = Validation.buildDefaultValidatorFactory();
    validator = validatorFactory.getValidator();
  }

  @AfterAll
  public static void close() {
    validatorFactory.close();
  }

  @Test
  public void shouldHaveNoViolations() {
    //given:
    Address address = Address.builder()
            .line1( ADDRESS_LINE1 )
            .line2( ADDRESS_LINE2 )
            .city( ADDRESS_CITY )
            .countryCode( ADDRESS_COUNTRY_CODE )
            .client( ADDRESS_CLIENT )
            .build();

    //when:
    Set<ConstraintViolation<Address>> violations
            = validator.validate(address);

    //then:
    assertTrue(violations.isEmpty());
  }

  @Test
  public void shouldDetectInvalidLine1() {
    //given too short name:
    Address address = Address.builder()
            .line1( "L" )
            .line2( ADDRESS_LINE2 )
            .city( ADDRESS_CITY )
            .countryCode( ADDRESS_COUNTRY_CODE )
            .client( ADDRESS_CLIENT )
            .build();

    //when:
    Set<ConstraintViolation<Address>> violations = validator.validate(address);

    //then:
    assertEquals(1, violations.size());

    ConstraintViolation<Address> violation = violations.iterator().next();
    assertEquals("size must be between 2 and 40", violation.getMessage());
    assertEquals("line1", violation.getPropertyPath().toString());
    assertEquals("L", violation.getInvalidValue());
  }

  @Test
  public void shouldDetectInvalidLine2() {
    //given too short name:
    Address address = Address.builder()
            .line1( ADDRESS_LINE1 )
            .line2( "L" )
            .city( ADDRESS_CITY )
            .countryCode( ADDRESS_COUNTRY_CODE )
            .client( ADDRESS_CLIENT )
            .build();

    //when:
    Set<ConstraintViolation<Address>> violations = validator.validate(address);

    //then:
    assertEquals(1, violations.size());

    ConstraintViolation<Address> violation = violations.iterator().next();
    assertEquals("size must be between 2 and 40", violation.getMessage());
    assertEquals("line2", violation.getPropertyPath().toString());
    assertEquals("L", violation.getInvalidValue());
  }

  @Test
  public void shouldDetectInvalidCity() {
    //given too short name:
    Address address = Address.builder()
            .line1( ADDRESS_LINE1 )
            .line2( ADDRESS_LINE2 )
            .city( "Aaaaaaaaaa AAAAAAAAAAA BBBBBBBBBBb dddddddddddddd eeeeeeeeeeeeee ffffffffffff ggggggggggg" )
            .countryCode( ADDRESS_COUNTRY_CODE )
            .client( ADDRESS_CLIENT )
            .build();

    //when:
    Set<ConstraintViolation<Address>> violations = validator.validate(address);

    //then:
    assertEquals( 1, violations.size());

    ConstraintViolation<Address> violation = violations.iterator().next();
    assertEquals("size must be between 2 and 40", violation.getMessage());
    assertEquals("city", violation.getPropertyPath().toString());
    assertEquals("Aaaaaaaaaa AAAAAAAAAAA BBBBBBBBBBb dddddddddddddd eeeeeeeeeeeeee ffffffffffff ggggggggggg", violation.getInvalidValue());
  }

  @Test
  public void shouldDetectInvalidCountryCode() {
    //given too short name:
    Address address = Address.builder()
            .line1( ADDRESS_LINE1 )
            .line2( ADDRESS_LINE2 )
            .city( ADDRESS_CITY )
            .countryCode( "ITA" )
            .client( ADDRESS_CLIENT )
            .build();

    //when:
    Set<ConstraintViolation<Address>> violations = validator.validate(address);

    //then:
    assertEquals( 1, violations.size());

    ConstraintViolation<Address> violation = violations.iterator().next();
    assertEquals("size must be between 2 and 2", violation.getMessage());
    assertEquals("countryCode", violation.getPropertyPath().toString());
    assertEquals("ITA", violation.getInvalidValue());
  }

  @Test
  public void shouldDetectInvalidClient() {
    //given too short name:
    Address address = Address.builder()
            .line1( ADDRESS_LINE1 )
            .line2( ADDRESS_LINE2 )
            .city( ADDRESS_CITY )
            .countryCode( ADDRESS_COUNTRY_CODE )
            .build();

    //when:
    Set<ConstraintViolation<Address>> violations = validator.validate(address);

    //then:
    assertEquals( 1, violations.size());

    ConstraintViolation<Address> violation = violations.iterator().next();
    assertEquals("must not be null", violation.getMessage());
    assertEquals("client", violation.getPropertyPath().toString());
    assertEquals(null, violation.getInvalidValue());
  }
}

标签: java

解决方案


实体是数据库的增强镜像(实例是 SSOT,类是 SVOT),M im MVC,它们是 bean。是否应该对 bean 进行单元测试:不。

您所做的是在实体中混合 M 和 C。C是否应该进行单元测试?Yes!!!.

所以你真的应该测试它们!


推荐阅读