Skip to content

Commit

Permalink
Added matcher for json keys. Fixes #4
Browse files Browse the repository at this point in the history
  • Loading branch information
CellDynamics committed Jun 4, 2017
1 parent 7945c1a commit 880b8cd
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 0 deletions.
17 changes: 17 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,17 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<useReleaseProfile>false</useReleaseProfile>
<releaseProfiles>sonatype</releaseProfiles>
<goals>deploy</goals>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
Expand Down Expand Up @@ -266,6 +277,12 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
</dependencies>
<reporting>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package com.github.baniuk.ImageJTestSuite.matchers.json;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.hamcrest.collection.IsIterableContainingInAnyOrder;

import com.google.gson.Gson;

/**
* Hamcrest extension.
*
* <p>Compare keys in json output. Values are ignored.
*
* @author p.baniukiewicz
*/
public class JsonKeysMatcher extends TypeSafeDiagnosingMatcher<String> {

private final String expected;

/**
* Main constructor.
*
* @param expected expected file.
*/
public JsonKeysMatcher(String expected) {
this.expected = expected;
}

/*
* (non-Javadoc)
*
* @see org.hamcrest.SelfDescribing#describeTo(org.hamcrest.Description)
*/
@Override
public void describeTo(Description description) {
description.appendText("Same keys in JSons.");
}

/*
* (non-Javadoc)
*
* @see org.hamcrest.TypeSafeDiagnosingMatcher#matchesSafely(java.lang.Object,
* org.hamcrest.Description)
*/
@Override
protected boolean matchesSafely(String compared, Description mismatchDescription) {
List<String> keysTest;
List<String> keysRef;

try {
keysTest = getKeysFromJson(expected);
keysRef = getKeysFromJson(compared);
} catch (Exception e) {
mismatchDescription.appendText("can not validate json: " + e.getMessage());
return false;
}

Matcher<?> equalsMatcher = IsIterableContainingInAnyOrder.containsInAnyOrder(keysRef.toArray());
if (!equalsMatcher.matches(keysTest)) {
mismatchDescription.appendText("was: ").appendDescriptionOf(equalsMatcher);
return false;
} else {
return true;
}
}

/**
* Extract keys from json.
*
* @param jsoString json string
* @return list of keys
* @throws Exception Exception
*/
public static List<String> getKeysFromJson(String jsoString) throws Exception {
Object things = new Gson().fromJson(jsoString, Object.class);
List<String> keys = new ArrayList<String>();
collectAllTheKeys(keys, things);
return keys;
}

/**
* Iterate through json levels and gather keys.
*
* @param keys levels
* @param o values on levels
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void collectAllTheKeys(List keys, Object o) {
Collection values = null;
if (o instanceof Map) {
Map map = (Map) o;
keys.addAll(map.keySet()); // collect keys at current level in hierarchy
values = map.values();
} else if (o instanceof Collection) {
values = (Collection) o;
} else {
return;
}

for (Object value : values) {
collectAllTheKeys(keys, value);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.github.baniuk.ImageJTestSuite.matchers.json;

/**
* @author p.baniukiewicz
*
*/
public class JsonMatchers {

/**
* Compare two Json strings through their keys. Values are ignored.
*
* <pre>
* <code>
* assertThat(compared, haveSameKeys(expected);
* </code>
* </pre>
*
* @param expected json string that gives expected keys in json
* @return instance
*/
public static JsonKeysMatcher haveSameKeys(String expected) {
return new JsonKeysMatcher(expected);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* Contain matchers related to json.
*
* @author p.baniukiewicz
*
*/
package com.github.baniuk.ImageJTestSuite.matchers.json;
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package com.github.baniuk.ImageJTestSuite.matchers.json;

import static com.github.baniuk.ImageJTestSuite.matchers.json.JsonMatchers.haveSameKeys;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.MatcherAssert.assertThat;

import org.junit.Test;

/**
* @author p.baniukiewicz
*
*/
public class JsonKeysMatcherTest {

/**
* Same keys, different vals
*
* @throws Exception Exception
*/
@Test
public void testHaveSameKeys_same() throws Exception {
//!>
String json1 = "{\"menu\": {"+
" \"id\": \"file\","+
"\"value\": \"Fileeeee\","+
"\"popup\": {"+
"\"menuitem\": ["+
"{\"value\": \"Neweee\", \"onclick\": \"CreateNewDoc()\"},"+
"{\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},"+
"{\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}"+
"]"+
"}"+
"}}";
String json2 = "{\"menu\": {"+
" \"id\": \"file\","+
"\"value\": \"File\","+
"\"popup\": {"+
"\"menuitem\": ["+
"{\"value\": \"New\", \"onclick\": \"CreateNewDoc()\"},"+
"{\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},"+
"{\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}"+
"]"+
"}"+
"}}";
//!<
assertThat(json1, is(haveSameKeys(json2)));
}

/**
* Different keys, different vals
*
* @throws Exception Exception
*/
@Test
public void testHaveSameKeys_diff() throws Exception {
//!>
String json1 = "{\"menu\": {"+
" \"ideee\": \"file\","+
"\"value\": \"Fileeeee\","+
"\"popup\": {"+
"\"menuitem\": ["+
"{\"value\": \"Neweee\", \"onclick\": \"CreateNewDoc()\"},"+
"{\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},"+
"{\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}"+
"]"+
"}"+
"}}";
String json2 = "{\"menu\": {"+
" \"id\": \"file\","+
"\"value\": \"File\","+
"\"popup\": {"+
"\"menuitem\": ["+
"{\"value\": \"New\", \"onclick\": \"CreateNewDoc()\"},"+
"{\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},"+
"{\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}"+
"]"+
"}"+
"}}";
//!<
assertThat(json1, is(not(haveSameKeys(json2))));
}

/**
* Less keys, different vals
*
* @throws Exception Exception
*/
@Test
public void testHaveSameKeys_less() throws Exception {
//!>
String json1 = "{\"menu\": {"+
"\"value\": \"Fileeeee\","+
"\"popup\": {"+
"\"menuitem\": ["+
"{\"value\": \"Neweee\", \"onclick\": \"CreateNewDoc()\"},"+
"{\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},"+
"{\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}"+
"]"+
"}"+
"}}";
String json2 = "{\"menu\": {"+
" \"id\": \"file\","+
"\"value\": \"File\","+
"\"popup\": {"+
"\"menuitem\": ["+
"{\"value\": \"New\", \"onclick\": \"CreateNewDoc()\"},"+
"{\"value\": \"Open\", \"onclick\": \"OpenDoc()\"},"+
"{\"value\": \"Close\", \"onclick\": \"CloseDoc()\"}"+
"]"+
"}"+
"}}";
//!<
assertThat(json1, is(not(haveSameKeys(json2))));
}
}

0 comments on commit 880b8cd

Please sign in to comment.