I am using Grails 3.1.9 and I'm trying to understand how to test services. Here is my entity:
class Flight {
String number
Plane plane
Airport origin
Airport destination
LocalDate departureDate
LocalTime departureTime
LocalDate arrivalDate
LocalTime arrivalTime
BigDecimal ticketPrice
boolean cancelled
static hasMany = [
bookings: Booking
]
static constraints = {
}
}
And here is my service:
#Transactional
class FlightService {
List<Flight> search(Airport from, Airport to, LocalDate on) {
return Flight.findAllByOriginAndDestinationAndDepartureDate(from, to, on)
}
}
And here is my test:
#TestFor(FlightService)
#Mock([Flight])
class FlightServiceSpec extends Specification {
def setup() {
}
def cleanup() {
}
void "test search"() {
when:
def sfo = new Airport(code: 'SFO', city: 'San Francisco', countryCode: 'US', timeZone: ZoneId.of("America/Los_Angeles"))
def bru = new Airport(code: 'BRU', city: 'Brussels', countryCode: 'BE', timeZone: ZoneId.of("Europe/Brussels"))
service.search(bru, sfo, LocalDate.of(2016, 8, 31))
then:
1 * Flight.findAllByOriginAndDestinationAndDepartureDate(*_)
}
}
But when I run grails test-app, I get the following exception in the report:
org.springframework.dao.InvalidDataAccessResourceUsageException: Cannot query [com.epseelon.atr.Flight] on non-existent property: departureDate
at org.grails.datastore.mapping.simple.query.SimpleMapQuery.getValidProperty(SimpleMapQuery.groovy:751)
at org.grails.datastore.mapping.simple.query.SimpleMapQuery.executeSubQueryInternal(SimpleMapQuery.groovy:690)
at org.grails.datastore.mapping.simple.query.SimpleMapQuery.executeSubQuery(SimpleMapQuery.groovy:676)
at org.grails.datastore.mapping.simple.query.SimpleMapQuery.executeQuery(SimpleMapQuery.groovy:63)
at org.grails.datastore.mapping.query.Query.list(Query.java:567)
at org.grails.datastore.gorm.finders.FindAllByFinder.invokeQuery(FindAllByFinder.java:49)
at org.grails.datastore.gorm.finders.FindAllByFinder$1.doInSession(FindAllByFinder.java:43)
at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:310)
at org.grails.datastore.gorm.finders.AbstractFinder.execute(AbstractFinder.java:41)
at org.grails.datastore.gorm.finders.FindAllByFinder.doInvokeInternal(FindAllByFinder.java:40)
at org.grails.datastore.gorm.finders.DynamicFinder.invoke(DynamicFinder.java:157)
at org.grails.datastore.gorm.finders.DynamicFinder.invoke(DynamicFinder.java:357)
at org.grails.datastore.gorm.GormStaticApi.methodMissing(GormStaticApi.groovy:141)
at org.grails.datastore.gorm.GormEntity$Trait$Helper.staticMethodMissing(GormEntity.groovy:745)
at com.epseelon.atr.FlightService.$tt__search(FlightService.groovy:11)
at com.epseelon.atr.FlightService.search_closure1(FlightService.groovy)
at groovy.lang.Closure.call(Closure.java:414)
at groovy.lang.Closure.call(Closure.java:430)
at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:96)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:93)
at com.epseelon.atr.FlightServiceSpec.test search(FlightServiceSpec.groovy:27)
Which I don't understand since there IS a departureDate property on the Flight entity.
Add this to your specifications to enable the joda time unit test support
def setupSpec() {
SimpleMapJodaTimeMarshaller.initialize();
}
See https://github.com/gpc/joda-time/issues/14
Related
I am developing one application in grails. I have following kind of mapping. Now I am saving object of DemoD class but its not saving values neither showing me any error while save. I have printed all created object and all looks fine. but still I am now able to save records.
class DemoS {
String firstName
String lastName
Long rollNumber
String address1
String address2
String city
String state
static constraints = {
address2 nullable:true
}
static hasMany = [demoAList: DemoA]
}
class DemoD {
Date date
static hasMany = [demoAList: DemoA]
def beforeInsert = {
date = new Date()
}
}
class DemoA {
Long id
Boolean absent
Boolean halfday
String notes
Date date
static belongsTo = [demoS:DemoS, demoD:DemoD]
static constraints = {
notes nullable: true
}
}
class UploadDataService {
def saveUploadedData(def dataList) {
def i = 0
DemoD ddObj = new DemoD()
//Getting this dataList from excel and now creating object for each row.
dataList?.each{ rowList ->
if(i != 0){
def dsObj = DemoS.get(rowList[0]?.longValue())
DemoA daObj = new DemoA([id:rowList[0]?.longValue(),absent:rowList[1],halfday:rowList[2],notes:rowList[3] ? rowList[3] : ''])
dsObj.addToDemoAList(daObj)
daObj.demoS = dsObj
ddObj.addToDemoAList(daObj)
daObj.demoD = ddObj
}
i++
}
ddObj.save(saveOnError: true)
}
}
I've been baffled by this behavior for a few hours now. I'm using grails 2.4.2 and spock for testing. I have a domain object like so:
class AccRegStrDb implements Serializable {
BigInteger accountId
String keyName
BigInteger indexNumber
String value
static mapping = {
version false
keyName column: "`key`"
indexNumber column: "`index`"
id generator:'assigned',
composite: ['accountId', 'keyName', 'indexNumber']
}
}
Notice that my class has static mapping lines. In my spock test, I'm trying to test a service that saves the object into the DB. I have the following code:
#TestFor(AccountRecordService)
#Mock([AccRegStrDb])
class AccountRecordServiceSpec extends Specification {
def setup() {
}
def cleanup() {
}
void "saveValue() of String saves to AccRegStrDb"() {
when:
service.saveValue(2000000, "keyName", "string")
then:
1 == AccRegStrDb.count()
}
}
My service looks like this:
#Transactional
class AccountRecordService {
public void saveValue(Long accountId, String keyName, String value) {
def test = new AccRegStrDb(
accountId: accountId,
keyName: keyName,
indexNumber: BigInteger.ZERO,
value: value
).save(flush: true, failOnError: true)
}
}
On test-app, my assertion fails because the object wasn't saved. No weird errors whatsoever. When I remove the static mapping in my class, the assertion passes. What could be wrong? Any help?
:D
Solved it, by removing generator:'assigned' in my domain class. So, it now looks like this:
class AccRegStrDb implements Serializable {
BigInteger accountId
String keyName
BigInteger indexNumber
String value
static mapping = {
version false
keyName column: "`key`"
indexNumber column: "`index`"
id composite: ['accountId', 'keyName', 'indexNumber']
}
}
I need to disable (or make them for example red) specific dates in SmartGWT DateChooser. I was trying to use setDisabledDates(Date... disabledDates) and change cssStyle using setDisabledWeeenddayStyle, but it takes no effect. Any ideas how can I do that?
public class CustomDateItem extends DateItem {
private DateChooser chooser = new DateChooser();
public CustomDateItem() {
this("", "");
}
public CustomDateItem(String name, String title) {
super(name, title);
onInit();
}
private void onInit() {
Date date = new Date(2014, 06, 27);
chooser.setDisabledDates(date);
setPickerProperties(chooser);
}
}
This is my DateItem.java. However, if i try something like this:
public class CustomDateItem extends DateItem {
public CustomDateItem() {
this("", "");
}
public CustomDateItem(String name, String title) {
super(name, title);
onInit();
}
private void onInit() {
Date date = new Date(2014, 06, 27);
System.out.println(date);
getPickerProperties().setDisabledDates(date);
}
}
i got js error:
com.google.gwt.core.client.JavaScriptException: (TypeError) #com.smartgwt.client.util.JSOHelper::setAttribute(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;)([null, string: 'disabledDates', JavaScript object(341)]): elem is null
but as you can see, "date" is not null and getPickerProperties() creates its own DateChooser.
Ok, resolved. Dates has to be declarated just like this:
Calendar cal1 = new GregorianCalendar(2014, 05, 26);
and all code should look like this:
public class DateItem extends com.smartgwt.client.widgets.form.fields.DateItem {
private DateChooser chooser = new DateChooser();
public DateItem(String name, String title) {
super(name, title);
onInit();
}
private void onInit() {
Calendar cal1 = new GregorianCalendar(2014, 05, 26);
Date[] dates = new Date[]{cal1.getTime()};
chooser.setDisabledDates(dates);
chooser.setDisabledWeekdayStyle("holidays");
chooser.setDisabledWeekendStyle("holidays");
setPickerProperties(chooser);
}
}
Hope it will help someone.
I have three domain objects
class OrgProfile {
String name
static mapping = {
discriminator column:'ORG_TYPE'
}
}
class Org extends OrgProfile {
static mapping = {
discriminator 'ORG'
}
}
class Jurisdiction extends OrgProfile {
String email
static mapping{
discriminator 'JURISDICTION'
}
}
I need to search by name and email to get all list of Org and Jurisdiction
so something like
def criteria = OrgProfile.createCriteria()
criteria.list{
or {
ilike("name", "%${token}%")
ilike("email", "%${token}%")
}
}
where token is a string. How can this be achieved?
Tried the code:
def criteria = OrgProfile.createCriteria()
def results = criteria.list{
or {
ilike("name", "%${token}%")
ilike("email", "%${token}%")
}
}
Results as expected.
I am new to groovy/grails, and I'm trying to to do a criteria search that finds all posts for a month, basically like this:
def getUserMinutesForYear(User user, Date date){
Date firstDate = new GregorianCalendar(date.year, Calendar.JANUARY, 1, 0, 0, 0).time
Date lastDate = new GregorianCalendar(date.year, Calendar.DECEMBER, 31, 23, 59, 59).time
def c = JobRegistration.createCriteria()
def minutes = c.get {
and{
eq("user.id", user.id)
between("job.happening", firstDate, lastDate)
}
projections {
sum("minutesWorked")
}
}
return minutes
}
The domain classes are
class Job {
String title
String description
Date happening
static hasMany = [registrations:JobRegistration]
}
class User {
static hasMany = [authorities: Role, registrations: JobRegistration]
static belongsTo = Role
String username
}
class JobRegistration {
Job job
User user
Integer minutesWorked
static belongsTo = [user:User,job:Job]
static constraints = {
user(blank: false)
job(blank:false)
minutesWorked(nullable :true)
}
String toString(){
return user.userRealName
}
}
Now, why do I get this exception?
org.codehaus.groovy.runtime.InvokerInvocationException: org.hibernate.QueryException: could not resolve property: job.happening of: JobRegistration
You need to nest the job relationship (you can also just us eq with user):
def minutes = c.get {
and{
eq("user", user)
job{
between("happening", firstDate, lastDate)
}
}
projections {
sum("minutesWorked")
}
}
cheers
Lee