My grails unit test for domain class is throwing this exception:
| 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)
Following is my stripped down Domain class :
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)
}
}
My com.pkg.common.Configuration class is just a Singleton with static properties :
package com.pkg.common
import grails.util.Holders
class Configuration{
final public static String ALLOWED_TEXT_CHARS = "${Holders.grailsApplication.metadata["allowed.text.chars"]}"
}
"allowed.text.chars" is a RegEx defined in application.properties :
allowed.text.chars=[a-zA-Z0-9\\p{L}\\p{Digit}_"` $ \\-'_&;\:#()/\\.,!\\?%*|<>]+
Now, why this much pain just to set up a constraint ? Well, I need to keep all text fields across my 15+ domains, consistent in terms of characters they accept. Since this is business driven requirement, I need to keep it configurable, so that we can remove/add any new chars at any time, without the risk of touching too many domain classes for the sake of integrity. In addition to that, I want to use the available regex in other Service classes as well.
Now, this implementation works well in run-app, production & test-app integration: Only problem is with Unit tests cases. What I can understand is, that such dependencies, Grails won't be able to inject automatically, in a unit-test env.
Can we mock & add Configuration class using metaClass manipulation ? I have tried but failed.(read: I am not aware how mocking for Static classes work and how to add them to metaClass)
Or, if there's another way to implement such kind of concept ?
Many Thnx
To avoid repeating the constraint across multiple domain classes, you could use either a shared constraint or a global constraint.
If you use a global constraint, then to enable you to access the regex from a service class, store the regex in a separate config param.
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
}
}
If you want to write a unit test that tests the domain class' constraint remember to add the @Mock
annotation, e.g.
@Mock([DomainClass])
class DomainClassTests {
void testConstraint() {
// test code goes here
}
}