Testing criteria in Grails 2.2 - grails-2.0

One of the reasons we are moving from Grails 1.3.7 to 2.2 is for the ability to unit test our (many) criteria.
And the first thing we have run into with criteria testing is this:
Property [nightly.id] is not a valid property of class [com.litle.bldvwr.Result]
at grails.gorm.CriteriaBuilder.validatePropertyName(CriteriaBuilder.java:968)
What we have is a simple many to one relationship between result and nightly.
Each Result has 1 nightly. There is no direct relationship between Nightly and Result.
Updated
The specific code is:
Nightly.groovy:
package examples
import java.util.Date;
class Nightly {
String name
String status
static constraints = {
status nullable:true
name unique: true, nullable: false, blank: false
}
static mapping = {
}
String toString () {
name +' ' + status
}
}
Result.groovy:
package examples
import java.util.Date;
class Result {
String status
String name
String type
Nightly nightly
static mapping = {
}
Result() {
}
static def gimmeCountByNightlyAndStatusAndRerunIsNull(def nightly, def status) {
def count = Result.createCriteria().count {
and {
eq('nightly.id', nightly.id)
eq('status', status)
isNull('rerun')
}
}
return count
}
}
ResultTests.groovy
package examples
import grails.test.mixin.*
import org.junit.*
#TestFor(Result)
#Mock(Nightly)
class ResultTests {
void testCriteriaMess () {
//this test will fail due to: Property [nightly.id] is not a valid property of class [examples.Result]
Nightly night = new Nightly( name:'nightly1', status:'Success')
night.save(validate:false)
Result res = new Result(status: 'SUCCESS', type: 'INTEGRATION')
res.nightly = night
res.save(validate:false, flush:true)
def count = Result.gimmeCountByNightlyAndStatusAndRerunIsNull(night, 'SUCCESS')
assertTrue count==0
}
}
The above code is from a brand new Grails 2.2 project as created with GGTS 3.1
Except for the code above, everything else in the project is complete boiler plate has generated.
I would expect that, as it does against the actual database, 'nightly.id' would be translated into the nightly_id column of the Result table.
Is this an issue with how GORM is being mocked in 2.2, or are we missing something?

You should change the query to
def count = Result.createCriteria().count {
and {
eq('nightly', nightly)
eq('status', status)
isNull('rerun')
}
}

Related

javafx binding from list property to arbitrary object property

I am trying to get a class to have a property bound to another class's list property, where the 1st property is derived from a summarizing calculation over the objects in the list. The code below is a simplified version of my production code. (The production code is doing a summary over DateTime objects -- the essential part of the code below is the binding between a list and an object property (here, it is a String for simplicity).)
I have tried various things. One approach was using addListener on the list in the Summary class below but I was running into weird bugs with the listener callback making updates on the Summary object. After doing a bunch of reading I think that a binding between the summary string and the list is more appropriate but I don't know exactly how to hook up the binding to the property?
package com.example.demo.view
import javafx.beans.Observable
import javafx.beans.binding.StringBinding
import javafx.beans.property.SimpleIntegerProperty
import javafx.beans.property.SimpleListProperty
import javafx.beans.property.SimpleStringProperty
import javafx.collections.FXCollections
import tornadofx.View
import tornadofx.button
import tornadofx.label
import tornadofx.vbox
class Thing(x: Int) {
val xProperty = SimpleIntegerProperty(x)
val yProperty = SimpleStringProperty("xyz")
}
class Collection {
private var things = FXCollections.observableList(mutableListOf<Thing>()) {
arrayOf<Observable>(it.xProperty)
}
val thingsProperty = SimpleListProperty<Thing>(things)
fun addThing(thing: Thing) {
things.add(thing)
}
}
class Summary(var collection: Collection) {
val summaryBinding = object : StringBinding() {
// The real code is more practical but
// this is just a minimal example.
override fun computeValue(): String {
val sum = collection.thingsProperty.value
.map { it.xProperty.value }
.fold(0, { total, next -> total + next })
return "There are $sum things."
}
}
// How to make this property update when collection changes?
val summaryProperty = SimpleStringProperty("There are ? things.")
}
class MainView : View() {
val summary = Summary(Collection())
override val root = vbox {
label(summary.summaryProperty)
button("Add Thing") {
summary.collection.addThing(Thing(5))
}
}
}
Keep in mind that I made this answer based on your minimal example:
class Thing(x: Int) {
val xProperty = SimpleIntegerProperty(x)
var x by xProperty
val yProperty = SimpleStringProperty("xyz")
var y by yProperty
}
class MainView : View() {
val things = FXCollections.observableList(mutableListOf<Thing>()) {
arrayOf<Observable>(it.xProperty)
}
val thingsProperty = SimpleListProperty<Thing>(things)
val totalBinding = integerBinding(listProperty) {
value.map { it.x }.fold(0, { total, next -> total + next })
}
val phraseBinding = stringBinding(totalBinding) { "There are $value things." }
override val root = vbox {
label(phraseBinding)
button("Add Thing") {
action {
list.add(Thing(5))
}
}
}
}
I removed your other classes because I didn't see a reason for them based on the example. If the collection class has more functionality than holding a list property in your real project, then add just add it back in. If not, then there's no reason to give a list its own class. The summary class is really just two bindings (or one if you have no need to separate the total from the phrase). I don't see the need to give them their own class either unless you plan on using them in multiple views.
I think your biggest problem is that you didn't wrap your button's action in action {}. So your code just added a Thing(5) on init and had no action set.
P.S. The var x by xProperty stuff will only work if you import tornadofx.* for that file.

How to parse a Spring 5 WebClient response in a non-blocking way?

I'm using Spring WebFlux WebClient to retrieve data from an external API, like this:
public WeatherWebClient() {
this.weatherWebClient = WebClient.create("http://api.openweathermap.org/data/2.5/weather");
}
public Mono<String> getWeatherByCityName(String cityName) {
return weatherWebClient
.get()
.uri(uriBuilder -> uriBuilder
.queryParam("q", cityName)
.queryParam("units", "metric")
.queryParam("appid", API_KEY)
.build())
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(String.class);
}
This works fine and produces a response like this:
{
"coord":{
"lon":-47.06,
"lat":-22.91
},
"weather":[
{
"id":800,
"main":"Clear",
"description":"clear sky",
"icon":"01d"
}
],
"base":"stations",
"main":{
"temp":16,
"pressure":1020,
"humidity":67,
"temp_min":16,
"temp_max":16
},
"visibility":10000,
"wind":{
"speed":1,
"deg":90
},
"clouds":{
"all":0
},
"dt":1527937200,
"sys":{
"type":1,
"id":4521,
"message":0.0038,
"country":"BR",
"sunrise":1527932532,
"sunset":1527971422
},
"id":3467865,
"name":"Campinas",
"cod":200
}
But I'm only interested in the "temp" property (main -> temp). How could I transform the response (using Jackson's ObjectMapper, for example) to return only "temp" value in a reactive/non-blocking way?
I understand the first thing is replacing ".retrieve()" by ".exchange()" but I can't figure out how to make it work.
PS: This is my first question here. Please let me know if I'm doing something wrong or if you need more details.
Thanks!
You need to create a type that corresponds to the response sent by the server. A very minimal example could be like this:
#JsonIgnoreProperties(ignoreUnknown = true)
public class WeatherResponse {
public MainWeatherData main;
}
and the MainWeatherData class could be:
#JsonIgnoreProperties(ignoreUnknown = true)
public class MainWeatherData {
public String temp;
}
Finally, you could use WeatherResponse in bodyToMono:
...
.retrieve()
.bodyToMono(WeatherResponse.class);
The #JsonIgnoreProperties(ignoreUnknown = true)annotation instructs Jackson to not give any errors if it encounters any value in JSON string that is not present in you POJO.
You can access the WeatherResponseobject with a chained map operator:
getWeatherByCityName(cityName)
.map(weatherResponse -> weatherResponse.main.temp)

"could not determine data type of parameter $1" with Postgres

I am facing this seem to be famous issue by setting a timestamp binding against postgres.
#Test
public void testGetCurrentDate() {
NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(datasources.get(dbType));
PlatformTransactionManager manager = new DataSourceTransactionManager(datasources.get(dbType));
final Timestamp ts = new Timestamp(System
.currentTimeMillis());
new TransactionTemplate(manager).execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
template.update("create table test_timestamp (col timestamp)", Collections.emptyMap());
template.update("insert into test_timestamp (col) values (:TS) ", Collections.singletonMap("TS", ts));
}
});
Assert.assertEquals((Integer) 1, new TransactionTemplate(manager).execute(new TransactionCallback<Integer>() {
#Override
public Integer doInTransaction(TransactionStatus status) {
MapSqlParameterSource paramsSource = new MapSqlParameterSource();
paramsSource.addValue("TS", ts, Types.TIMESTAMP, "timestamp");
return template.queryForObject("select 1 from test_timestamp where :TS is not null and col=:TS ", paramsSource,
Integer.class);
}
}));
}
This test fails with ERROR: could not determine data type of parameter $1
See here the discution with postgres about that:
http://www.postgresql-archive.org/quot-could-not-determine-data-type-of-parameter-quot-with-timestamp-td5995489.html
I already have a workaround for that (Setting a PGTimestamp instance instead of Timestamp). I was wondering if it is something that could benefits to Spring JDBC to increase portability accross multiple databases.
In this case the workaround would be something like this in org.springframework.jdbc.core.StatementCreatorUtils ( around line 380):
else if (sqlType == Types.TIMESTAMP &&
"PostgreSQL".equals(ps.getConnection().getMetaData().getDatabaseProductName()))) {
Class<?> pgTimestampClass = Class.forName("org.postgresql.util.PGTimestamp");
Timestamp ts = (Timestamp)pgTimestampClass.getConstructor(long.class).newInstance(javaValue.getTime());
ps.setTimestamp(paramIndex, ts);
If you think that it something that makes sense, I could propose a pull request.
Arnaud

Firebase Dynamic Querying using results of barcode scanner (Ionic 3 & Angularfire2)

I have a case where I need to dynamically retrieve the results of a specific book. I would like to retrieve that specific book by using its ISBN number (highlighted in bold below). This is how my database looks like:
{
"results" :
{
"key1" : {
"Character_Depth" : 4,
"Dialogue" : 4,
"Plot" : 5,
"Theme" : 3,
"Writing_Style" : 3,
"bookName" : "Ionic",
"isbnNumber" : "0123456789012"
},
"key2" : {
"Character_Depth" : 4,
"Dialogue" : 4,
"Plot" : 4,
"Theme" : 2,
"Writing_Style" : 4,
"bookName" : "Justin",
"isbnNumber" : "036000291452"
}
}
}
Before I dive into the code, here is some important information I think you need to know. What I am trying to specifically do is use a barcode scanner to scan the ISBN number of a book. Then I would like to use that scanned ISBN number to dynamically retrieve results from that database. With that being said, I need to design my code in such a way that the barcode scanner variable is updated every single time (with each scan) to the new barcode number (already completed). Then that barcode number is fed into the query (which I still can't get to work, and is what I need help with) which retrieves a child node based on that number.
My code:
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams, AlertController } from 'ionic-angular';
import { BarcodeScanner, BarcodeScannerOptions } from '#ionic-native/barcode-scanner';
import { AngularFireAuth } from 'angularfire2/auth';
import { AngularFireDatabase, AngularFireList } from 'angularfire2/database';
import { HomePage } from '../home/home';
import { Observable } from 'rxjs/Observable';
#IonicPage()
#Component({
selector: 'page-login',
templateUrl: 'login.html',
})
export class LoginPage {
bookResults: Observable<any[]>;
options: BarcodeScannerOptions;
results: {};
constructor(public navCtrl: NavController,
public navParams: NavParams,
private fire: AngularFireAuth,
private database: AngularFireDatabase,
private barcodeScanner: BarcodeScanner,
private alertCtrl: AlertController) {
/* ########## part of the code where I specifically need help ########## */
this.bookResults = this.database.list('results').valueChanges();
}
/* ########### Barcode scanner function */
async Scan(){
this.results = await this.barcodeScanner.scan();
console.log(this.results);
}
}
Right now, what happens is that the "this.bookResults = this.database.list('results').valueChanges();" retrieves the above database. However, I need some guidance as to how to change my query such that I can retrieve specific child nodes based on the "isbnNumber" instance of each child.
I've tried several things. More recently I've tried:
this.bookResults = this.database.list('/results', {
query: {
orderByChild: isbnNumber,
equalTo: this.results,
}
});
but that didn't work. I've tried other things such as:
this.bookResults =
this.database.list('/results/${this.results}').valueChanges();
but it hasn't worked either.
I've read various stackoverflow threads, so I wouldn't be surprised if this was marked as duplicate. I have tried following the instructions of various threads, yet I felt that the way retrieving information from the database didn't specifically apply to my current situation, as the values used to retrieve specific child nodes where hardcoded into the query. I need a dynamically changing query that adjusts itself based on the barcode scanner's results).
Please let me know if there is anything that was unclear from this post, and I'd be more than happy to help. Also, if you are interested in seeing the source code, here is a link to my github repo containing it:
https://github.com/islamaymansais/honey_scanner
(go to src -> pages -> login -> login.ts)
Thanks for taking the time to read this long post. I am a beginner , I've gone through plenty of posts but unfortunately I was not able to apply the appropriate changes due to my lack of experience with ionic.
As per the readme notes for the Angular firebase library the following should work:
constructor(public navCtrl: NavController,
public navParams: NavParams,
private fire: AngularFireAuth,
private database: AngularFireDatabase,
private barcodeScanner: BarcodeScanner,
private alertCtrl: AlertController) {
this.getData();
}
async function Scan(){
this.results = await this.barcodeScanner.scan();
console.log(this.results);
this.getData();
}
this.getData = () => {
var scanned_Barcode_Text = "";
if (Object.keys(this.results).length > 0){
if(typeof this.results['text'] != 'undefined' && this.results['text'] != ""){
scanned_Barcode_Text = this.results['text'];
}
}
this.bookResults = this.database.list('/results',
ref => (scanned_Barcode_Text != "") ? ref.orderByChild('isbnNumber').equalTo(scanned_Barcode_Text) : ref
).snapshotChanges();
}
call the getData() function in the constructor and also in the success function of the barcode scan.
The orderBy and equal to queries can only be called on the reference objects which is the second parameter(optional) of the AngularFireDatabase object. The usage is similar to the reduce function of the Array.prototype.
Hope this helps.
Try this.
let booksRef = this.firebase.database().ref("results/");
booksRef.orderByChild("isbnNumber").equalTo(scannedBarCode).on("child_added", function(data) {
console.log(data.val());
this.bookResults = data.val();
});
I am considering that you have got the barcode value already and have it in the variable scannerBarCode.
Sidenote: In my opinion, since you are querying the database on ISBN, you should use that instead of key. It will make it simple. Also try the new Cloud Firestore that has better querying features.

Using Moq can you verify a method call with an anonymous type?

I'm trying to verify a method call using Moq, but I can't quite get the syntax right. Currently, I've got this as my verify:
repository.Verify(x => x.ExecuteNonQuery("fav_AddFavorites", new
{
fid = 123,
inputStr = "000456"
}), Times.Once());
The code compiles, but the test fails with the error:
Expected invocation on the mock once, but was 0 times:
x => x.ExecuteNonQuery("fav_AddFavorites", new <>f__AnonymousType0<Int32, String>(123, "000456"))
No setups configured.
Performed invocations:
IRepository.ExecuteNonQuery("fav_AddFavorites", { fid = 123, inputStr = 000456 })
How can I verify the method call and match the method parameters for an anonymous type?
UPDATE
To answer the questions:
I am trying to verify both that the method was called and that the parameters are correct.
The signature of the method I'm trying to verify is:
int ExecuteNonQuery(string query, object param = null);
The setup code is simply:
repository = new Mock<IRepository>();
UPDATE 2
It looks like this is a problem with Moq and how it handles anonymous types in .Net. The code posted by Paul Matovich runs fine, however, once the code and the test are in different assemblies the test fails.
This Passes
public class Class1
{
private Class2 _Class2;
public Class1(Class2 class2)
{
_Class2 = class2;
}
public void DoSomething(string s)
{
_Class2.ExecuteNonQuery(s, new { fid = 123, inputStr = "000456" });
}
}
public class Class2
{
public virtual void ExecuteNonQuery(string s, object o)
{
}
}
/// <summary>
///A test for ExecuteNonQuery
///</summary>
[TestMethod()]
public void ExecuteNonQueryTest()
{
string testString = "Hello";
var Class2Stub = new Mock<Class2>();
Class1 target = new Class1(Class2Stub.Object);
target.DoSomething(testString);
Class2Stub.Verify(x => x.ExecuteNonQuery(testString, It.Is<object>(o => o.Equals(new { fid = 123, inputStr = "000456" }))), Times.Once());
}
##Update##
That is strange, it doesn't work in different assemblies. Someone can give us the long definition about why the object.equals from different assemblies behaves differently, but for different assemblies, this will work, any variance in the object values will return a different hash code.
Class2Stub.Verify(x => x.ExecuteNonQuery(testString, It.Is<object>(o => o.GetHashCode() == (new { fid = 123, inputStr = "000456" }).GetHashCode())), Times.Once());
One option is to "verify" it in a Callback. Obviously this needs to be done at Setup time, e.g.:
aMock.Setup(x => x.Method(It.IsAny<object>())).Callback<object>(
(p1) =>
{
dynamic o = p1;
Assert.That(o.Name, Is.EqualTo("Bilbo"));
});
None of the answers are great when your test assembly is different than the system under test's assembly (really common). Here's my solution that uses JSON serialization and then strings comparison.
Test Helper Function:
using Newtonsoft.Json;
public static class VerifyHelper
{
public static bool AreEqualObjects(object expected, object actual)
{
var expectedJson = JsonConvert.SerializeObject(expected);
var actualJson = JsonConvert.SerializeObject(actual);
return expectedJson == actualJson;
}
}
Example System Under Test:
public void DoWork(string input)
{
var obj = new { Prop1 = input };
dependency.SomeDependencyFunction(obj);
}
Example Unit Test:
var expectedObject = new { Prop1 = "foo" };
sut.DoWork("foo");
dependency.Verify(x => x.SomeDependencyFunction(It.Is<object>(y => VerifyHelper.AreEqualObjects(expectedObject, y))), Times.Once());
This solution is really simple, and I think makes the unit test easier to understand as opposed to the other answers in this thread. However, because it using simple string comparison, the test's anonymous object has to be set up exactly the same as the system under the test's anonymous object. Ergo, let's say you only cared to verify the value of a single property, but your system under test sets additional properties on the anonymous object, your unit test will need to set all those other properties (and in the same exact order) for the helper function to return true.
I created a reusable method based on Pauls answer:
object ItIsAnonymousObject(object value)
{
return It.Is<object>(o => o.GetHashCode() == value.GetHashCode());
}
...
dependency.Verify(
x => x.SomeDependencyFunction(ItIsAnonymousObject(new { Prop1 = "foo" })),
Times.Once());
Also, this can be used for property name case-insensitive comparison:
protected object ItIsAnonymousObject(object value)
{
var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
return It.Is<object>(o => JsonSerializer.Serialize(o, options) == JsonSerializer.Serialize(value, options));
}

Resources