diff --git a/liquibase-core/src/main/java/liquibase/change/custom/CustomChangeWrapper.java b/liquibase-core/src/main/java/liquibase/change/custom/CustomChangeWrapper.java index f86c0b68025..59a6696660f 100644 --- a/liquibase-core/src/main/java/liquibase/change/custom/CustomChangeWrapper.java +++ b/liquibase-core/src/main/java/liquibase/change/custom/CustomChangeWrapper.java @@ -291,7 +291,11 @@ public String getSerializedObjectNamespace() { @Override public void load(ParsedNode parsedNode, ResourceAccessor resourceAccessor) throws ParsedNodeException { try { - setClass(parsedNode.getChildValue(null, "class", String.class)); + String classNameValue = parsedNode.getChildValue(null, "class", String.class); + if (classNameValue == null) { + throw new ParsedNodeException("Custom change node has no 'class' attribute!"); + } + setClass(classNameValue); } catch (CustomChangeException e) { throw new ParsedNodeException(e); } diff --git a/liquibase-core/src/test/groovy/liquibase/change/custom/CustomChangeWrapperTest.groovy b/liquibase-core/src/test/groovy/liquibase/change/custom/CustomChangeWrapperTest.groovy index 2c2df21ee8f..3adb9dc52f2 100644 --- a/liquibase-core/src/test/groovy/liquibase/change/custom/CustomChangeWrapperTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/change/custom/CustomChangeWrapperTest.groovy @@ -273,6 +273,16 @@ class CustomChangeWrapperTest extends Specification { } + def "customChange without class fails expectedly"() { + when: + def node = new ParsedNode(null, "customChange") + def change = new CustomChangeWrapper() + change.load(node, resourceSupplier.simpleResourceAccessor) + + then: + thrown(ParsedNodeException.class) + } + def "load handles params in a 'params' collection"() { when: def node = new ParsedNode(null, "customChange")