Модульный тест класса домена Grails, проблема с настройкой ограничения - java.lang.NoClassDefFoundError: Не удалось инициализировать

Мой модульный тест Grails для класса домена выдает это исключение:

|  java.lang.NoClassDefFoundError: Could not initialize class com.pkg.common.Configuration
    at com.pkg.DomainClass$__clinit__closure1.doCall(DomainClass.groovy:10)
    at org.grails.datastore.mapping.config.groovy.MappingConfigurationBuilder.evaluate(MappingConfigurationBuilder.groovy:72)
    at org.grails.datastore.mapping.config.AbstractGormMappingFactory.createMappedForm(AbstractGormMappingFactory.java:51)
    at org.grails.datastore.mapping.keyvalue.mapping.config.GormKeyValueMappingFactory.createMappedForm(GormKeyValueMappingFactory.java:37)
    at org.grails.datastore.mapping.keyvalue.mapping.config.GormKeyValueMappingFactory.createMappedForm(GormKeyValueMappingFactory.java:27)
    at org.grails.datastore.mapping.keyvalue.mapping.config.KeyValuePersistentEntity.<init>(KeyValuePersistentEntity.java:33)
    at org.grails.datastore.mapping.keyvalue.mapping.config.KeyValueMappingContext.createPersistentEntity(KeyValueMappingContext.java:89)
    at org.grails.datastore.mapping.model.AbstractMappingContext.addPersistentEntityInternal(AbstractMappingContext.java:159)
    at org.grails.datastore.mapping.model.AbstractMappingContext.addPersistentEntity(AbstractMappingContext.java:152)
    at grails.test.mixin.domain.DomainClassUnitTestMixin.mockDomain(DomainClassUnitTestMixin.groovy:133)
    at grails.test.mixin.domain.DomainClassUnitTestMixin.mockDomain(DomainClassUnitTestMixin.groovy:129)

Ниже приведен мой урезанный класс домена:

package com.pkg

import com.pkg.common.Configuration

class DomainClass {

    String subject

    static constraints = {
        subject(maxSize: 100, nullable: false, blank: false, matches: Configuration.ALLOWED_TEXT_CHARS)
    }
}

Мой класс com.pkg.common.Configuration - это просто Singleton со статическими свойствами:

package com.pkg.common

import grails.util.Holders

class Configuration{
    final public static String ALLOWED_TEXT_CHARS = "${Holders.grailsApplication.metadata["allowed.text.chars"]}"
}

"allow.text.chars" - это RegEx, определенный в application.properties:

allowed.text.chars=[a-zA-Z0-9\\p{L}\\p{Digit}_"` $ \\-'_&;\:#()/\\.,!\\?%*|<>]+

Теперь, почему это так больно, просто чтобы установить ограничение? Ну, мне нужно сохранить все текстовые поля в моих 15+ доменах, согласованные с точки зрения символов, которые они принимают. Поскольку это бизнес-требование, мне нужно сохранить его настраиваемым, чтобы мы могли в любое время удалить / добавить любые новые символы без риска трогать слишком много классов домена ради целостности. В дополнение к этому, я хочу использовать доступное регулярное выражение и в других классах Service.

Теперь эта реализация хорошо работает в интеграции run-app, production & test-app: единственная проблема - в случаях модульных тестов. Что я могу понять, так это то, что такие зависимости Grails не сможет внедрить автоматически в модульном тесте env.

Можем ли мы смоделировать и добавить класс конфигурации, используя метакласс манипуляции? Я пытался, но потерпел неудачу. (Читай: я не знаю, как работают насмешки для статических классов и как добавить их в метакласс)

Или, если есть другой способ реализовать такую ​​концепцию?

Многие Thnx

1 ответ

Решение

Чтобы избежать повторения ограничения для нескольких классов домена, вы можете использовать либо общее ограничение, либо глобальное ограничение.

Если вы используете глобальное ограничение, то для предоставления вам доступа к регулярному выражению из класса обслуживания сохраните регулярное выражение в отдельном параметре конфигурации.

Config.groovy

allowed.text.chars='bigLongRegex'

grails.gorm.default.constraints = {
    subject matches: allowed.text.chars
}

Класс обслуживания

class MyService {

   GrailsApplication grailsApplication

   void something() {
      String regex = grailsApplication.config.allowed.text.chars
   }
}

Если вы хотите написать модульный тест, который проверяет ограничение класса домена, не забудьте добавить @Mock аннотация, например

@Mock([DomainClass])
class DomainClassTests {
   void testConstraint() {
     // test code goes here
   }
}
Другие вопросы по тегам