Add a few more tests with repository validation rules with profiles

This commit is contained in:
Martha Mitran 2023-12-14 16:08:27 -08:00
parent 5ed382228d
commit be1d3fac76
1 changed files with 121 additions and 9 deletions

View File

@ -2,8 +2,13 @@ package ca.uhn.fhir.jpa.validation;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
import ca.uhn.fhir.jpa.interceptor.validation.IRepositoryValidatingRule;
import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingInterceptor;
import ca.uhn.fhir.jpa.interceptor.validation.RepositoryValidatingRuleBuilder;
import ca.uhn.fhir.jpa.test.BaseJpaR4Test;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.SingleValidationMessage;
import ca.uhn.fhir.validation.ValidationResult;
@ -16,21 +21,37 @@ import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.StructureDefinition;
import org.hl7.fhir.r5.utils.validation.constants.BestPracticeWarningLevel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
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 static org.junit.jupiter.api.Assertions.fail;
public class ResourceValidationR4Test extends BaseJpaR4Test {
private static final FhirContext ourCtx = FhirContext.forR4();
private static FhirValidator myFhirValidator;
private static PrePopulatedValidationSupport ourValidationSupport;
private static final String myResourceType = "Patient";
private static final String myResourceTypeDefinition = "http://hl7.org/fhir/StructureDefinition/Patient";
private static final String PATIENT_STRUCTURE_DEFINITION_URL = "http://example.org/fhir/StructureDefinition/TestPatient";
private final RepositoryValidatingInterceptor myRepositoryValidatingInterceptor = new RepositoryValidatingInterceptor(ourCtx, Collections.emptyList());
@Autowired
private ApplicationContext myApplicationContext;
@BeforeAll
public static void setup() {
myFhirValidator = ourCtx.newValidator();
@ -50,6 +71,16 @@ public class ResourceValidationR4Test extends BaseJpaR4Test {
myFhirValidator.registerValidatorModule(myInstanceVal);
}
@BeforeEach
public void before() {
myInterceptorRegistry.registerInterceptor(myRepositoryValidatingInterceptor);
}
@AfterEach
public void after() {
myInterceptorRegistry.unregisterInterceptor(myRepositoryValidatingInterceptor);
}
@Test
public void testCreateStructureDefinition_createMultipleWithWithSameUrl_isStoredSuccessfully() {
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "1", "Patient.identifier");
@ -71,7 +102,7 @@ public class ResourceValidationR4Test extends BaseJpaR4Test {
assertEquals(1, validationResult.getMessages().size());
SingleValidationMessage message = validationResult.getMessages().iterator().next();
assertTrue(message.getMessage().contains( PATIENT_STRUCTURE_DEFINITION_URL + "|1"));
assertEquals("Patient.identifier: minimum required = 1, but only found 0 (from " + PATIENT_STRUCTURE_DEFINITION_URL + "|1)", message.getMessage());
}
@Test
@ -88,12 +119,12 @@ public class ResourceValidationR4Test extends BaseJpaR4Test {
assertEquals(1, validationResult.getMessages().size());
SingleValidationMessage message = validationResult.getMessages().iterator().next();
assertTrue(message.getMessage().contains(PATIENT_STRUCTURE_DEFINITION_URL + "|2"));
assertEquals("Patient.name: minimum required = 1, but only found 0 (from " + PATIENT_STRUCTURE_DEFINITION_URL + "|2)", message.getMessage());
}
@Test
public void testValidatePatient_withMultipleProfilesDifferentUrls_validatesAgainstAllProfiles() {
final String sdIdentifier = PATIENT_STRUCTURE_DEFINITION_URL + "-identifier";
final String sdIdentifier = PATIENT_STRUCTURE_DEFINITION_URL + "-identifier";
final String sdName = PATIENT_STRUCTURE_DEFINITION_URL + "-name";
createPatientStructureDefinitionWithMandatoryField(sdIdentifier, "1", "Patient.identifier");
createPatientStructureDefinitionWithMandatoryField(sdName, "1", "Patient.name");
@ -107,11 +138,10 @@ public class ResourceValidationR4Test extends BaseJpaR4Test {
assertEquals(2, validationResult.getMessages().size());
Iterator<SingleValidationMessage> messageIterator = validationResult.getMessages().iterator();
assertTrue(messageIterator.next().getMessage().contains(sdIdentifier));
assertTrue(messageIterator.next().getMessage().contains(sdName));
assertEquals("Patient.identifier: minimum required = 1, but only found 0 (from " + PATIENT_STRUCTURE_DEFINITION_URL + "-identifier|1)", messageIterator.next().getMessage());
assertEquals("Patient.name: minimum required = 1, but only found 0 (from " + PATIENT_STRUCTURE_DEFINITION_URL + "-name|1)", messageIterator.next().getMessage());
}
@Test
public void testStructureDefinition_createResourceWithMultipleProfilesSameStructureDefinition_usesFirstVersion() {
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "1", "Patient.identifier");
@ -130,14 +160,83 @@ public class ResourceValidationR4Test extends BaseJpaR4Test {
assertEquals(1, validationResult.getMessages().size());
SingleValidationMessage message = validationResult.getMessages().iterator().next();
assertTrue(message.getMessage().contains(PATIENT_STRUCTURE_DEFINITION_URL + "|1"));
assertEquals("Patient.identifier: minimum required = 1, but only found 0 (from " + PATIENT_STRUCTURE_DEFINITION_URL + "|1)", message.getMessage());
}
@Test
public void testCreatePatient_withRepositoryValidationRuleNoVersionProfileNoVersion_validatesAgainstFirstVersion() {
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "1", "Patient.identifier");
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "2", "Patient.name");
setupRepositoryValidationRules(PATIENT_STRUCTURE_DEFINITION_URL);
Patient patient = new Patient();
patient.getMeta().addProfile(PATIENT_STRUCTURE_DEFINITION_URL);
try {
myPatientDao.create(patient, mySrd);
fail();
} catch (PreconditionFailedException e) {
ourLog.info(e.getMessage());
assertEquals(Msg.code(574) + "Patient.identifier: minimum required = 1, but only found 0 (from " + PATIENT_STRUCTURE_DEFINITION_URL + "|1)", e.getMessage());
}
}
@Test
public void testCreatePatient_withRepositoryValidationRuleWithVersionProfileWithVersion_unknownProfile() {
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "1", "Patient.identifier");
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "2", "Patient.name");
setupRepositoryValidationRules(PATIENT_STRUCTURE_DEFINITION_URL + "|1");
Patient patient = new Patient();
patient.getMeta().addProfile(PATIENT_STRUCTURE_DEFINITION_URL + "|1");
try {
myPatientDao.create(patient, mySrd);
fail();
} catch (PreconditionFailedException e) {
assertEquals(Msg.code(574) + "Profile reference '" + PATIENT_STRUCTURE_DEFINITION_URL + "|1' has not been checked because it is unknown, and the validator is set to not fetch unknown profiles", e.getMessage());
}
}
@Test
public void testCreatePatient_withRepositoryValidationRuleNoVersionProfileWithVersion_doesNotConform() {
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "1", "Patient.identifier");
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "2", "Patient.name");
setupRepositoryValidationRules(PATIENT_STRUCTURE_DEFINITION_URL);
Patient patient = new Patient();
patient.getMeta().addProfile(PATIENT_STRUCTURE_DEFINITION_URL + "|1");
try {
myPatientDao.create(patient, mySrd);
fail();
} catch (PreconditionFailedException e) {
assertEquals(Msg.code(575) + "Resource of type \"" + myResourceType + "\" does not declare conformance to profile from: [" + PATIENT_STRUCTURE_DEFINITION_URL + "]", e.getMessage());
}
}
@Test
public void testCreatePatient_withRepositoryValidationRuleWithVersionProfileWithoutVersion_doesNotConform() {
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "1", "Patient.identifier");
createPatientStructureDefinitionWithMandatoryField(PATIENT_STRUCTURE_DEFINITION_URL, "2", "Patient.name");
setupRepositoryValidationRules(PATIENT_STRUCTURE_DEFINITION_URL + "|1");
Patient patient = new Patient();
patient.getMeta().addProfile(PATIENT_STRUCTURE_DEFINITION_URL);
try {
myPatientDao.create(patient, mySrd);
fail();
} catch (PreconditionFailedException e) {
assertEquals(Msg.code(575) + "Resource of type \"" + myResourceType + "\" does not declare conformance to profile from: [" + PATIENT_STRUCTURE_DEFINITION_URL + "|1]", e.getMessage());
}
}
private void createPatientStructureDefinitionWithMandatoryField(String theUrl, String theVersion, String thePath) {
StructureDefinition sd = new StructureDefinition()
.setUrl(theUrl).setVersion(theVersion)
.setBaseDefinition("http://hl7.org/fhir/StructureDefinition/Patient")
.setType("Patient")
.setBaseDefinition(myResourceTypeDefinition)
.setType(myResourceType)
.setDerivation(StructureDefinition.TypeDerivationRule.CONSTRAINT);
sd.getDifferential().addElement()
.setPath(thePath)
@ -148,4 +247,17 @@ public class ResourceValidationR4Test extends BaseJpaR4Test {
assertTrue(outcome.getCreated());
ourValidationSupport.addStructureDefinition(sd);
}
private void setupRepositoryValidationRules(String... theProfiles) {
List<IRepositoryValidatingRule> rules = myApplicationContext.getBean(RepositoryValidatingRuleBuilder.REPOSITORY_VALIDATING_RULE_BUILDER, RepositoryValidatingRuleBuilder.class)
.forResourcesOfType(myResourceType)
.requireAtLeastOneProfileOf(theProfiles)
.and()
.requireValidationToDeclaredProfiles()
.withBestPracticeWarningLevel(BestPracticeWarningLevel.Ignore)
.rejectOnSeverity("error")
.build();
myRepositoryValidatingInterceptor.setRules(rules);
}
}