Skip to main content
added 683 characters in body
Source Link
Mercury
  • 81
  • 1
  • 5

After reading about Value Objects, I think they're pretty cool and should be used, but I am not sure if I am doing it the right way.

Let's assume that I have a simple DTO to create a user, which contains information that should be validated (e.g., the email must be valid, the birthdate cannot be in the future, etc.) from a technical point of view. At the same time, I have a business requirement such as the user can't be younger than 14 years old, and I don't think that hardcoding this into the Birthdate class is a good idea. I think it would be better to move this validation to another service.

public class CreateUserPayloadDto {
  @JsonPropery("email")
  Email email; // user's email
  @JsonPropery("birthdate")
  Birthdate birthdate; // user's birthdate
}

If I use Value Objects in the DTO, I can't test negative cases properly (for example, if the birthdate is in the future, then BAD REQUEST must be returned).

I have come up with three solutions:

  • Do not use Value Objects but use Java Bean Validation (then convert it to a POJO with Value Objects inside).
  • Use Value Objects and do not write tests for negative cases.
  • Create a separate DTO that uses primitives but is the same as the DTO with Value Objects, and test it this way. See example of code below
public class CreateUserPayloadDto {
  @JsonPropery("email")
  String email; // user's email
  @JsonPropery("birthdate")
  String birthdate; // user's birthdate
}

If you need more info, I will provide it as soon as I can. Thank you!

UPD:

Here is an example of my integration test:

@SpringBootTest
@AutoConfigureWebTestClient
public CreateUserEndpointTest {

  @Autowired
  WebTestClient webTestClient;

  @Test
  public void shouldReturn400BadRequestIfBirthdateIsInTheFuture() {
    final CreateUserPayloadDto body = CreateUserPayloadDto.builder()
          // I can't do this, because Birthdate cannot be instantiated 
          // since it is invalid!
         .birthdate(Birthdate.of(LocalDate.now().plusYears(1)))
         .build();

    final WebTestClient.ResponseSpec responseSpec = sendRequest(body);
    
    responseSpec.expectStatus().isBadRequest();
  }
}

After reading about Value Objects, I think they're pretty cool and should be used, but I am not sure if I am doing it the right way.

Let's assume that I have a simple DTO to create a user, which contains information that should be validated (e.g., the email must be valid, the birthdate cannot be in the future, etc.) from a technical point of view. At the same time, I have a business requirement such as the user can't be younger than 14 years old, and I don't think that hardcoding this into the Birthdate class is a good idea. I think it would be better to move this validation to another service.

public class CreateUserPayloadDto {
  @JsonPropery("email")
  Email email; // user's email
  @JsonPropery("birthdate")
  Birthdate birthdate; // user's birthdate
}

If I use Value Objects in the DTO, I can't test negative cases properly (for example, if the birthdate is in the future, then BAD REQUEST must be returned).

I have come up with three solutions:

  • Do not use Value Objects but use Java Bean Validation (then convert it to a POJO with Value Objects inside).
  • Use Value Objects and do not write tests for negative cases.
  • Create a separate DTO that uses primitives but is the same as the DTO with Value Objects, and test it this way. See example of code below
public class CreateUserPayloadDto {
  @JsonPropery("email")
  String email; // user's email
  @JsonPropery("birthdate")
  String birthdate; // user's birthdate
}

If you need more info, I will provide it as soon as I can. Thank you!

After reading about Value Objects, I think they're pretty cool and should be used, but I am not sure if I am doing it the right way.

Let's assume that I have a simple DTO to create a user, which contains information that should be validated (e.g., the email must be valid, the birthdate cannot be in the future, etc.) from a technical point of view. At the same time, I have a business requirement such as the user can't be younger than 14 years old, and I don't think that hardcoding this into the Birthdate class is a good idea. I think it would be better to move this validation to another service.

public class CreateUserPayloadDto {
  @JsonPropery("email")
  Email email; // user's email
  @JsonPropery("birthdate")
  Birthdate birthdate; // user's birthdate
}

If I use Value Objects in the DTO, I can't test negative cases properly (for example, if the birthdate is in the future, then BAD REQUEST must be returned).

I have come up with three solutions:

  • Do not use Value Objects but use Java Bean Validation (then convert it to a POJO with Value Objects inside).
  • Use Value Objects and do not write tests for negative cases.
  • Create a separate DTO that uses primitives but is the same as the DTO with Value Objects, and test it this way. See example of code below
public class CreateUserPayloadDto {
  @JsonPropery("email")
  String email; // user's email
  @JsonPropery("birthdate")
  String birthdate; // user's birthdate
}

If you need more info, I will provide it as soon as I can. Thank you!

UPD:

Here is an example of my integration test:

@SpringBootTest
@AutoConfigureWebTestClient
public CreateUserEndpointTest {

  @Autowired
  WebTestClient webTestClient;

  @Test
  public void shouldReturn400BadRequestIfBirthdateIsInTheFuture() {
    final CreateUserPayloadDto body = CreateUserPayloadDto.builder()
          // I can't do this, because Birthdate cannot be instantiated 
          // since it is invalid!
         .birthdate(Birthdate.of(LocalDate.now().plusYears(1)))
         .build();

    final WebTestClient.ResponseSpec responseSpec = sendRequest(body);
    
    responseSpec.expectStatus().isBadRequest();
  }
}

Source Link
Mercury
  • 81
  • 1
  • 5

Should Value Objects be used inside the DTO?

After reading about Value Objects, I think they're pretty cool and should be used, but I am not sure if I am doing it the right way.

Let's assume that I have a simple DTO to create a user, which contains information that should be validated (e.g., the email must be valid, the birthdate cannot be in the future, etc.) from a technical point of view. At the same time, I have a business requirement such as the user can't be younger than 14 years old, and I don't think that hardcoding this into the Birthdate class is a good idea. I think it would be better to move this validation to another service.

public class CreateUserPayloadDto {
  @JsonPropery("email")
  Email email; // user's email
  @JsonPropery("birthdate")
  Birthdate birthdate; // user's birthdate
}

If I use Value Objects in the DTO, I can't test negative cases properly (for example, if the birthdate is in the future, then BAD REQUEST must be returned).

I have come up with three solutions:

  • Do not use Value Objects but use Java Bean Validation (then convert it to a POJO with Value Objects inside).
  • Use Value Objects and do not write tests for negative cases.
  • Create a separate DTO that uses primitives but is the same as the DTO with Value Objects, and test it this way. See example of code below
public class CreateUserPayloadDto {
  @JsonPropery("email")
  String email; // user's email
  @JsonPropery("birthdate")
  String birthdate; // user's birthdate
}

If you need more info, I will provide it as soon as I can. Thank you!