I have a problem migrating my old unit tests from grails 2.5.4 to grails 3.3
I have a lot of commands using shared preferences. An example, the UserCommand inside de UserController:
class UserCommand implements Validateable {
String firstName
static constraints = {
firstName shared: 'nonNullableString'
}
}
In the application.groovy I have defined the constraint this way:
grails.gorm.default.constraints = {
nonNullableString(blank: false, maxSize: 255)
}
Also I have the User domain defined as:
class User {
String firstName
static constraints = {
firstName shared: 'nonNullableString'
}
}
Writing a test I do:
User user = new User()
user.validate()
it works as expected. But when I do this:
UserCommand command = new UserCommand()
command.validate()
It throws an Exception.
`grails.gorm.validation.exceptions.ValidationConfigurationException: Property [User.firstName] references shared constraint [nonNullableString:null], which doesn't exist!`
I thought I made a mistake in the application.groovy file, but shared constraints works for the domains..
Here is a sample project with the same problem: https://github.com/almejo/commandtest
Any thoughts?
Related
I'm very new to grails web application! Here is my domain class
package imocha.project
class Feedback {
String name
String email
String type
String remark
static constraints = {
name(blank:true)
email(blank:true)
type(blank:false)
remark(blank:false)
}
}
In my case, I just want to set only the type and remark can't be blank! But at the end, it set all for me.
The reason for this is the default behavior for properties is nullable: false in a Grails project. Alter your constraints as follows:
package imocha.project
class Feedback {
String name
String email
String type
String remark
static constraints = {
name(nullable:true, blank:true)
email(nullable:true, blank:true)
type(blank:false)
remark(blank:false)
}
}
I have a domain class Plan which is like:
class Plan{
String name
static constraints={
name(unique:true,nullable:false)
}
}
Another domain class is User:
class User{
// Other attribures and code
// ....
Plan plan
static constraints = {
// other constraints..
plan(nullable:false, defaultValue: Plan.findByName("default"))
}
}
Above code gives me error:
Caused by: java.lang.IllegalStateException: Method on class [mypackage.Plan] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.
at mypackage.User$__clinit__closure1.doCall(User.groovy:31)
The line above in error is
plan(nullable:true,defaultValue: Plan.findByName("default"))
Also I have defined the default plan in BootStrap.groovy:
if(!Plan.findByName("default")){
new Plan(name: "default",brandPartner: null,secRole: null).save(failOnError: true, flush: true)
log.info("initPlans: No default plan found, hence created a new default plan!")
}
So how should I set the default value for plan attribute(which is of user defined type)?
Use an interceptor instead of constraint:
class User{
Plan plan
static beforeInsert = {
if( !plan ) Plan.withTransaction {
plan = Plan.findByName 'default'
}
}
}
I'm new to Grails. I'm developing a web app that handles the records of a gymnasium, to make routines, exercises, etc.
I have this domain class Ejercicios:
class Ejercicios {
String nombreEjercicio
String idHoja
String descripcion
List<String> descripcionO
static hasMany = [descripcionO: Descripciones]
static transients = ['descripcionTrans']
String descripcionTrans
static mapping = {
id column: "idHoja"
version false
}
static constraints = {
nombreEjercicio maxSize: 45
idHoja blank: false
}
The database table has the default Grails id named "idHoja", and another attribute named "id_hoja"
The thing here is that when I make a JSON parse from the rest API, I need GORM to look for exercises via the "id_hoja" attribute, not the "idHoja" because it'll cause a mismatch.
I found the solution by myself!
The only thing I needed to was to make the JSON call with the name "idHoja" and that was it.
I am new to Groovy & Grails. I am working on one of the sample one-to-many relationship in Grails.
The below is the code.
class User {
//properties
String login
String password
String role
//constraints and order of display of fields in UI
static constraints = {
login(blank: false, nullable: false, unique: true)
password(blank: false, nullable: false, password: true)
role(inList:["Admin", "Member"])
}
static hasMany = [posts : Post]
}
class Post {
String content
Date dateCreated
static constraints = {
content(blank: true)
}
static belongsTo = [user : User]
}
My Test class in Groovy
#TestFor(User)
class UserTests {
void testUserToPost() {
def user = new User(login: "joe", password: "joe", role:"Admin")
user.addToPosts(new Post(content: "First"));
user.addToPosts(new Post(content: "Second"));
user.addToPosts(new Post(content: "Third"));
user.save(flush: true)
assertEquals 3, User.get(user.id).posts.size()
}
}
While running the test class, getting following exception:
groovy.lang.MissingMethodException: No signature of method: com.library.forum.User.addToPosts() is applicable for argument types: (com.library.forum.Post) values: [com.library.forum.Post : (unsaved)]
Possible solutions: getPosts() at com.library.forum.UserTests.testUserToPost(UserTests.groovy:17)
Can anyone tell me where is the problem in code.
Since Grails 2.1.4, there's a change in mock behavior because of performance issue. So you need to mock all associated entities of the mocked entity.
See GRAILS-9637 - Due to a performance issue, #Mock no longer mocks
associated entities of the mocked entity. These have to be manually
specified. For example the following test will fail in 2.1.4 and
above:
#Mock(Author)
void testAddToBooks() {
def a = new Author()
a.addToBooks(new Book())
}
To correct the above test you need to mock both Author and Book:
#Mock([Author, Book])
void testAddToBooks() {
def a = new Author()
a.addToBooks(new Book())
}
You can check this reference.
You need to mock all related domain classes. Change :
#TestFor(User)
class UserTests {
to
#TestFor(User)
#Mock(Post)
class UserTests {
If you need, the mock annotation support a list of classes, for example: #Mock([Domain1, Domain2, Domain3])
I'm new to Grails and study it via InfoQ's "Getting Started With Grails" book.
Running through it I've faced a problem with the BootStrap.groovy file:
I've edited it as the book says.
Run-app it - and the data I've entered into BootStrap.groovy has been shown.
I've updated the bootstrapping values but they are not changed.
No errors are shown in the console.
What I've tried:
exchanging def's places;
set Runner's class value to nullables;
changed .save(failOnError:true) to .save(flush:true).
Even after I've changed the Race class' bootstrapping values it looks like it hasn't been changed.
Looks like the value is taken from somewhere else than the BootStrap.groovy?
I use Grails 2.2.1 with a PostgreSQL DB.
The classes' code is below:
package racetrack
class Runner {
static constraints = {
firstName(blank:false)
lastName(blank:false)
dateOfBirth(nullable:true)
gender(inList:["M","F"])
address(nullable:true)
city(nullable:true)
state(nullable:true)
zipcode(nullable:true)
email(email:true)
}
static hasMany = [registrations:Registration]
/*static mapping = {
sort "email"
}*/
String firstName
String lastName
Date dateOfBirth
String gender
String address
String city
String state
String zipcode
String email
String toString(){
"${firstName} ${lastName} (${email})"
}
}
and
package racetrack
class BootStrap {
def init = { servletContext ->
def begun = new Runner(firstName:"Marathon",
lastName:"Runner",
dateOfBirth:"",
gender:"M",
address:"",
city:"",
state:"",
zipcode:"",
email:"me#me.ru"
)
begun.save(flush:true)
def zabeg = new Race(name:"Run SPB",
startDate:new Date() + 360*30,
city:"Moscow",
state:"Moscow",
cost:10.0,
distance:42.0,
maxRunners:10)
zabeg.save(flush:true)
}
def destroy = {
}
}
EDIT: could this be happening due to any generate-* scripts been run?
Race.groovy:
package racetrack
class Race {
static hasMany = [registrations:Registration]
String name
Date startDate
String city
String state
BigDecimal distance
BigDecimal cost
Integer maxRunners
static constraints = {
name(blank:false, maxSize:50)
startDate(validator: {
return (it >= new Date())
}
)
city()
state(inList:["Moscow", "Volgograd", "SPb", "NN"])
distance(min:0.0)
cost(min:0.0, max:100.0)
maxRunners(min:0, max:100000)
}
static mapping = {
sort "startDate"
}
BigDecimal inMiles(){
return distance*0.6214
}
String toString(){
return "${name}, ${startDate.format('MM/dd/yyyy')}"
}
}
BootStrap should be in grails-app/conf instead. Refer this.
Try to print the errors of the new instance you save by adding
print begun.errors
See if somethings comes up.
You need to remove
def index() { }
from the controllers.
I had the same issue. Now it is fixed.