Skip to content

Commit

Permalink
Add enum discriminator tests
Browse files Browse the repository at this point in the history
Issue: #219
  • Loading branch information
muehmar committed Jan 2, 2024
1 parent 29560a9 commit e1848af
Show file tree
Hide file tree
Showing 13 changed files with 531 additions and 4 deletions.
2 changes: 1 addition & 1 deletion example-jakarta-3/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "com.github.muehmar.openapischema" version "2.4.1"
id "com.github.muehmar.openapischema" version "2.5.0-SNAPSHOT"
id "com.diffplug.spotless"
id 'openapischema.java'
}
Expand Down
7 changes: 6 additions & 1 deletion example/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id "com.github.muehmar.openapischema" version "2.4.1"
id "com.github.muehmar.openapischema" version "2.5.0-SNAPSHOT"
id "com.diffplug.spotless"
id 'openapischema.java'
id 'java-test-fixtures'
Expand Down Expand Up @@ -59,6 +59,7 @@ def specifications =
[name: 'freeform', file: 'openapi-freeform.yml'],
[name: 'validation', file: 'openapi-validation.yml'],
[name: 'oneof', file: 'openapi-oneof.yml'],
[name: 'oneofenumdiscriminator', file: 'openapi-oneof-enum-discriminator.yml'],
[name: 'anyof', file: 'openapi-anyof.yml'],
[name: 'allof', file: 'openapi-allof.yml'],
[name: 'identifiers', file: 'openapi-identifiers.yml'],
Expand Down Expand Up @@ -245,6 +246,10 @@ openApiGenerator {
builderMethodPrefix = ""

}
oneOfEnumDiscriminator {
inputSpec = "$projectDir/src/main/resources/openapi-oneof-enum-discriminator.yml"
packageName = "com.github.muehmar.gradle.openapi.oneofenumdiscriminator"
}
['71', '182', '185', '190', '191', '192', '193', '195', '209'].forEach {issueNumber -> {
"${issueNumber}" {
inputSpec = "$projectDir/src/main/resources/issues/openapi-issue-${issueNumber}.yml"
Expand Down
69 changes: 69 additions & 0 deletions example/src/main/resources/openapi-oneof-enum-discriminator.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
openapi: "3.0.0"
info: { }

paths: { }

components:
schemas:
User:
required:
- id
- username
allOf:
- $ref: '#/components/schemas/BaseUser'
properties:
id:
type: string
minLength: 5
username:
type: string
age:
type: integer
format: int32
minimum: 18
maximum: 199
writeOnly: true
email:
type: string
nullable: true
Admin:
required:
- id
- adminname
allOf:
- $ref: '#/components/schemas/BaseUser'
properties:
id:
type: string
minLength: 5
adminname:
type: string
level:
type: integer
format: int64
minimum: 1

BaseUser:
required:
- type
properties:
type:
type: string
enum:
- user
- admin

AdminOrUser:
oneOf:
- $ref: '#/components/schemas/Admin'
- $ref: '#/components/schemas/User'
discriminator:
propertyName: type
mapping:
admin: '#/components/schemas/Admin'
user: '#/components/schemas/User'





10 changes: 10 additions & 0 deletions example/src/main/resources/openapi-oneof.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ components:
discriminator:
propertyName: type

AdminOrUserDiscriminatorMapping:
oneOf:
- $ref: '#/components/schemas/Admin'
- $ref: '#/components/schemas/User'
discriminator:
propertyName: type
mapping:
adm: '#/components/schemas/Admin'
usr: '#/components/schemas/User'

OneOfMemberReference:
oneOf:
- $ref: '#/components/schemas/BaseOneOfMemberReference'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.github.muehmar.gradle.openapi.oneof;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.muehmar.gradle.openapi.util.MapperFactory;
import com.github.muehmar.openapi.util.Tristate;
import org.junit.jupiter.api.Test;

class DiscriminatorMappingDeserialisationTest {
private static final ObjectMapper MAPPER = MapperFactory.mapper();

@Test
void fold_when_matchesAdmin_then_adminDtoReturned() throws JsonProcessingException {
final AdminOrUserDiscriminatorMappingDto adminOrUserDto =
MAPPER.readValue(
"{\"id\":\"admin-id\",\"type\":\"adm\",\"adminname\":\"admin-name\",\"level\":5.5}",
AdminOrUserDiscriminatorMappingDto.class);

final Object obj = adminOrUserDto.foldOneOf(admin -> admin, user -> user);

final AdminDto adminDto =
AdminDto.builder()
.setId("admin-id")
.setType("adm")
.setAdminname("admin-name")
.andAllOptionals()
.setLevel(5L)
.build();
assertEquals(adminDto, obj);
}

@Test
void fold_when_matchesUser_then_userDtoReturned() throws JsonProcessingException {
final AdminOrUserDiscriminatorMappingDto adminOrUserDto =
MAPPER.readValue(
"{\"id\":\"user-id\",\"type\":\"usr\",\"username\":\"user-name\",\"age\":25,\"email\":null}",
AdminOrUserDiscriminatorMappingDto.class);

final Object obj = adminOrUserDto.foldOneOf(admin -> admin, user -> user);

final UserDto userDto =
UserDto.builder()
.setId("user-id")
.setType("usr")
.setUsername("user-name")
.andAllOptionals()
.setAge(25)
.setEmail(Tristate.ofNull())
.build();
assertEquals(userDto, obj);
}

@Test
void fold_when_invalidTypeWithoutOnInvalid_then_exceptionThrown() throws JsonProcessingException {
final AdminOrUserDiscriminatorMappingDto adminOrUserDto =
MAPPER.readValue(
"{\"id\":\"admin-id\",\"type\":\"Admin\",\"adminname\":\"admin-name\",\"level\":5.5}",
AdminOrUserDiscriminatorMappingDto.class);

assertThrows(
IllegalStateException.class, () -> adminOrUserDto.foldOneOf(admin -> admin, user -> user));
}

@Test
void fold_when_invalidTypeWithOnInvalid_then_onInvalidReturned() throws JsonProcessingException {
final AdminOrUserDiscriminatorMappingDto adminOrUserDto =
MAPPER.readValue(
"{\"id\":\"admin-id\",\"type\":\"Admin\",\"adminname\":\"admin-name\",\"level\":5.5}",
AdminOrUserDiscriminatorMappingDto.class);

final Object obj = adminOrUserDto.foldOneOf(admin -> admin, user -> user, () -> "invalid");

assertEquals("invalid", obj);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.github.muehmar.gradle.openapi.oneof;

import static org.junit.jupiter.api.Assertions.assertEquals;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.muehmar.gradle.openapi.util.MapperFactory;
import com.github.muehmar.openapi.util.Tristate;
import org.junit.jupiter.api.Test;

class DiscriminatorMappingSerialisationTest {
private static final ObjectMapper MAPPER = MapperFactory.mapper();

@Test
void writeValueAsString_when_adminDto_then_correctJson() throws JsonProcessingException {
final AdminDto adminDto =
AdminDto.builder()
.setId("admin-id")
.setType("type")
.setAdminname("admin-name")
.andAllOptionals()
.setLevel(5L)
.build();
final AdminOrUserDiscriminatorMappingDto dto =
AdminOrUserDiscriminatorMappingDto.builder().setAdminDto(adminDto).build();

assertEquals(
"{\"adminname\":\"admin-name\",\"id\":\"admin-id\",\"level\":5,\"type\":\"adm\"}",
MAPPER.writeValueAsString(dto));
}

@Test
void writeValueAsString_when_userDto_then_correctJson() throws JsonProcessingException {
final UserDto userDto =
UserDto.builder()
.setId("user-id")
.setType("type")
.setUsername("user-name")
.andAllOptionals()
.setAge(25)
.setEmail(Tristate.ofNull())
.build();
final AdminOrUserDiscriminatorMappingDto dto =
AdminOrUserDiscriminatorMappingDto.builder().setUserDto(userDto).build();

assertEquals(
"{\"age\":25,\"email\":null,\"id\":\"user-id\",\"type\":\"usr\",\"username\":\"user-name\"}",
MAPPER.writeValueAsString(dto));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.github.muehmar.gradle.openapi.oneof;

import static com.github.muehmar.gradle.openapi.util.ValidationUtil.validate;
import static com.github.muehmar.gradle.openapi.util.ViolationFormatter.formatViolations;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.muehmar.gradle.openapi.util.MapperFactory;
import java.util.Arrays;
import java.util.Set;
import javax.validation.ConstraintViolation;
import org.junit.jupiter.api.Test;

class DiscriminatorMappingValidationTest {

private static final ObjectMapper MAPPER = MapperFactory.mapper();

@Test
void validate_when_matchesUserSchema_then_noViolation() throws JsonProcessingException {
final AdminOrUserDiscriminatorMappingDto adminOrUserDto =
MAPPER.readValue(
"{\"id\":\"user-id\",\"type\":\"usr\",\"username\":\"user-name\",\"age\":25,\"email\":null}",
AdminOrUserDiscriminatorMappingDto.class);

final Set<ConstraintViolation<AdminOrUserDiscriminatorMappingDto>> violations =
validate(adminOrUserDto);

assertEquals(0, violations.size());
assertTrue(adminOrUserDto.isValid());
}

@Test
void validate_when_matchesUserSchemaButInvalidAge_then_violation()
throws JsonProcessingException {
final AdminOrUserDiscriminatorMappingDto adminOrUserDto =
MAPPER.readValue(
"{\"id\":\"user-id\",\"type\":\"usr\",\"username\":\"user-name\",\"age\":200,\"email\":null}",
AdminOrUserDiscriminatorMappingDto.class);

final Set<ConstraintViolation<AdminOrUserDiscriminatorMappingDto>> violations =
validate(adminOrUserDto);

assertEquals(
Arrays.asList(
"invalidOneOf[User].ageRaw -> must be less than or equal to 199",
"validAgainstNoOneOfSchema -> Is not valid against one of the schemas [Admin, User]",
"validAgainstTheCorrectSchema -> Not valid against the schema described by the discriminator"),
formatViolations(violations),
String.join("\n", formatViolations(violations)));
assertFalse(adminOrUserDto.isValid());
}

@Test
void validate_when_matchesNoSchema_then_violations() throws JsonProcessingException {
final AdminOrUserDiscriminatorMappingDto adminOrUserDto =
MAPPER.readValue("{}", AdminOrUserDiscriminatorMappingDto.class);

final Set<ConstraintViolation<AdminOrUserDiscriminatorMappingDto>> violations =
validate(adminOrUserDto);

assertEquals(
Arrays.asList(
"invalidOneOf[Admin].adminname -> must not be null",
"invalidOneOf[Admin].id -> must not be null",
"invalidOneOf[Admin].type -> must not be null",
"invalidOneOf[User].id -> must not be null",
"invalidOneOf[User].type -> must not be null",
"invalidOneOf[User].username -> must not be null",
"validAgainstNoOneOfSchema -> Is not valid against one of the schemas [Admin, User]",
"validAgainstTheCorrectSchema -> Not valid against the schema described by the discriminator"),
formatViolations(violations));
assertFalse(adminOrUserDto.isValid());
}

@Test
void validate_when_doesMatchBothSchemas_then_violation() throws JsonProcessingException {
final AdminOrUserDiscriminatorMappingDto adminOrUserDto =
MAPPER.readValue(
"{\"id\":\"id-123\",\"type\":\"usr\",\"username\":\"user-name\",\"adminname\":\"admin-name\",\"age\":25,\"email\":null}",
AdminOrUserDiscriminatorMappingDto.class);

final Set<ConstraintViolation<AdminOrUserDiscriminatorMappingDto>> violations =
validate(adminOrUserDto);

assertEquals(
Arrays.asList(
"validAgainstMoreThanOneSchema -> Is valid against more than one of the schemas [Admin, User]"),
formatViolations(violations));
assertFalse(adminOrUserDto.isValid());
}
}
Loading

0 comments on commit e1848af

Please sign in to comment.