├── .github
└── workflows
│ └── deploy-website.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── pom.xml
└── src
├── main
└── java
│ └── org
│ └── skyscreamer
│ └── jsonassert
│ ├── ArrayValueMatcher.java
│ ├── Customization.java
│ ├── FieldComparisonFailure.java
│ ├── JSONAssert.java
│ ├── JSONCompare.java
│ ├── JSONCompareMode.java
│ ├── JSONCompareResult.java
│ ├── JSONParser.java
│ ├── LocationAwareValueMatcher.java
│ ├── RegularExpressionValueMatcher.java
│ ├── ValueMatcher.java
│ ├── ValueMatcherException.java
│ └── comparator
│ ├── AbstractComparator.java
│ ├── ArraySizeComparator.java
│ ├── CustomComparator.java
│ ├── DefaultComparator.java
│ ├── JSONComparator.java
│ └── JSONCompareUtil.java
├── site
└── resources
│ ├── CNAME
│ ├── cookbook.html
│ ├── css
│ └── style.css
│ ├── index.html
│ └── quickstart.html
└── test
└── java
└── org
└── skyscreamer
└── jsonassert
├── ArrayValueMatcherTest.java
├── DependencyTest.java
├── JSONArrayWithNullTest.java
├── JSONAssertTest.java
├── JSONCompareModeTest.java
├── JSONCompareTest.java
├── JSONCustomComparatorTest.java
├── RegularExpressionValueMatcherTest.java
└── comparator
├── ArraySizeComparatorTest.java
├── CustomComparatorTest.java
└── JSONCompareUtilTest.java
/.github/workflows/deploy-website.yml:
--------------------------------------------------------------------------------
1 | # Simple workflow for deploying static content to GitHub Pages
2 | name: Deploy static content to Pages
3 |
4 | on:
5 | # Runs on pushes targeting the default branch - disabled, manual only
6 | #push:
7 | # branches: ["master"]
8 |
9 | # Allows you to run this workflow manually from the Actions tab
10 | workflow_dispatch:
11 |
12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
13 | permissions:
14 | contents: read
15 | pages: write
16 | id-token: write
17 |
18 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
19 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
20 | concurrency:
21 | group: "pages"
22 | cancel-in-progress: false
23 |
24 | jobs:
25 | # Single deploy job since we're just deploying
26 | deploy:
27 | environment:
28 | name: github-pages
29 | url: ${{ steps.deployment.outputs.page_url }}
30 | runs-on: ubuntu-latest
31 | steps:
32 | - name: Checkout
33 | uses: actions/checkout@v4
34 | - name: Setup Pages
35 | uses: actions/configure-pages@v5
36 | - uses: actions/setup-java@v4
37 | with:
38 | java-version: '17'
39 | distribution: 'temurin'
40 | cache: maven
41 | - name: Run the Maven javadoc command
42 | run: mvn javadoc:aggregate -DreportOutputDirectory=src/site/resources/apidocs
43 | - name: Upload artifact
44 | uses: actions/upload-pages-artifact@v3
45 | with:
46 | # Upload entire repository
47 | path: './src/site/resources'
48 | - name: Deploy to GitHub Pages
49 | id: deployment
50 | uses: actions/deploy-pages@v4
51 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | target
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | Changelog
2 | =========
3 |
4 | Version 2.0-rc1 - 7/28/2024
5 | -------------------
6 | - Release candidate
7 | - ** Switches JSON implementation to use org.json:json:20240303 **
8 | - Deployment still built with Java version 8 to maximize compatibility
9 | - Cannot insert null directly into JSONArray without casting. Recommend to use JSONObject.Null
10 | - JSONException is now a RuntimeException. Is not defined as thrown in method signatures anynmore.
11 |
12 | Version 1.5.3 - 6/28/2024
13 | -------------------------
14 | - Revert Java release version from 21 to 8 due to breaking older compilers.
15 |
16 | Version 1.5.2 - 6/14/2024
17 | -------------------------
18 | - Fix CVE-2020-15250 JUnit vulnerability (https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-15250). Bump
19 | dependencies.
20 | - Add gitIgnore file
21 | - README syntax error fix
22 | - Accidentally upgraded release to Java version 21
23 |
24 | Version 1.5.1 - 7/4/2022
25 | ------------------------
26 | Going to try to catch up on some ancient PRs, mainly around security and cleanup. Starting with accepted PRs that
27 | didn't get released yet. To be followed hopefully shortly with another release.
28 | - Added convenience methods for JSONObject comparison using a custom JSONComparator (thanks jakob-o@!)
29 | - Fix issue #105: Issue when comparing JSONArray if any value is null (thanks suraj1291993@!)
30 | - Fixes security vulnerability associated with older version of junit
31 |
32 | Version 1.5.0 - 3/19/2017
33 | -------------------------
34 | - JSONassert now supports user-supplied error messages (thanks yasin3061@!)
35 | - Some refactoring / code health cleanup (thanks picimako@!)
36 | - License headers on individual files
37 | - Java 8 friendly javadocs
38 |
39 | Version 1.4.0 - 10/30/2016
40 | --------------------------
41 | - Change the implementation for org.json to one with a more open license
42 | - Fix null pointer exception (issue #48)
43 | - Support wildcards in Customization.path
44 |
45 | Version 1.3.0 - 12/16/2015
46 | --------------------------
47 | - Fix & improve ArrayValueMatcher JavaDoc (thanks dmackinder@!)
48 | Fix final JavaDoc example and add new example showing how to verify
49 | every array element using a custom comparator
50 | - Fix URL in pom.xml (aukevanleeuwen@)
51 | - Update JSONCompareResult.java adding 2 new lists for missing and unexpected fileds (thanks riccorazza@!)
52 | - Includes missing imports in test class (thanks javierseixas@!)
53 |
54 | Version 1.2.3 - 2/5/2014
55 | ------------------------
56 | - This edition brought to you by dmackinder (thanks dmackinder!)
57 | - Added array size comparator enhancements.
58 | - Added ArrayValueMatcher to simplify verification of range of array elements.
59 | - Improve diagnostics from RegularExpressionValueMatcher.
60 | - Deprecated former Customization.matches() signature
61 |
62 | Version 1.2.2 - 12/31/2013
63 | --------------------------
64 | - Add support for JSONString
65 |
66 | Version 1.2.1 - 10/24/2013
67 | --------------------------
68 | - Remove commons-collection dependency
69 | - Updated Customization class to allow path-matching, and matching of expected and actual values with user-provided
70 | EqualityComparator.
71 | - Added AssertNotEquals
72 |
73 | Version 1.2.0 - 3/17/2013
74 | -------------------------
75 | - Fixed handling comparison of equivalent values across long, int, and double
76 | - Add JSONCompareMode to asserts to allow for more options than strict/not-strict
77 | - Added hooks to override/extend comparison behavior via JSONComparator
78 |
79 | Version 1.1.1 - 10/15/2012
80 | --------------------------
81 | - Return diagnostics (instead of throwing an exception) when comparing JSONObject and JSONArray
82 | - Expose field comparison results as a list in JSONCompareResult
83 | - Fix bug where actual JSON array doesn't contain JSONObjects with unique keys
84 | - Improve diagnostics
85 | - Unify some diagnostics
86 | - Fix handling of arrays of booleans
87 |
88 | Version 1.1.0 - 9/3/2012
89 | ------------------------
90 | - Added withStrictOrdering() and withExtensible() to JSONCompareMode
91 | - Javadoc fixes
92 | - Fix bug where expected and actual were reversed
93 | - Fix bug where nulls gave false positives in some cases
94 | - Simplified publishing Javadocs
95 |
96 | Version 1.0.0 - 4/5/2012
97 | ------------------------
98 | Initial release!
99 |
100 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
204 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | JSONassert
2 | ==========
3 |
4 | Write JSON unit tests in less code. Great for testing REST interfaces.
5 |
6 | Summary
7 | -------
8 |
9 | Write JSON tests as if you are comparing a string. Under the covers, JSONassert converts your string into a JSON object and compares the logical structure and data with the actual JSON. When _strict_ is set to false (recommended), it forgives reordering data and extending results (as long as all the expected elements are there), making tests less brittle.
10 |
11 | Supported test frameworks:
12 |
13 | * [JUnit](http://junit.org)
14 |
15 | Examples
16 | --------
17 |
18 | In JSONassert you write and maintain something like this:
19 |
20 | JSONObject data = getRESTData("/friends/367.json");
21 | String expected = "{friends:[{id:123,name:\"Corby Page\"},{id:456,name:\"Carter Page\"}]}";
22 | JSONAssert.assertEquals(expected, data, false);
23 |
24 | instead of all this:
25 |
26 |
54 |
55 | Error Messages
56 | --------------
57 |
58 | We tried to make error messages easy to understand. This is really important, since it gets hard for the eye to pick out the difference, particularly in long JSON strings. For example:
59 |
60 | String expected = "{id:1,name:\"Joe\",friends:[{id:2,name:\"Pat\",pets:[\"dog\"]},{id:3,name:\"Sue\",pets:[\"bird\",\"fish\"]}],pets:[]}";
61 | String actual = "{id:1,name:\"Joe\",friends:[{id:2,name:\"Pat\",pets:[\"dog\"]},{id:3,name:\"Sue\",pets:[\"cat\",\"fish\"]}],pets:[]}"
62 | JSONAssert.assertEquals(expected, actual, false);
63 |
64 | returns the following:
65 |
66 | friends[id=3].pets[]: Expected bird, but not found ; friends[id=3].pets[]: Contains cat, but not expected
67 |
68 | Which tells you that the pets array under the friend where id=3 was supposed to contain "bird", but had "cat" instead. (Maybe the cat ate the bird?)
69 |
70 | * * *
71 |
72 | QuickStart
73 | ----------
74 |
75 | To use, [download the JAR](https://github.com/skyscreamer/JSONassert/releases) or add the following to your project's pom.xml:
76 |
77 |
78 | org.skyscreamer
79 | jsonassert
80 | 2.0-rc1
81 | test
82 |
83 |
84 | Write tests like this:
85 |
86 | JSONAssert.assertEquals(expectedJSONString, actualJSON, strictMode);
87 |
88 | [More examples in our cookbook](http://jsonassert.skyscreamer.org/cookbook.html)
89 |
90 | * * *
91 |
92 | Who uses JSONassert?
93 | --------------------
94 | + [yoga](https://github.com/skyscreamer/yoga) - A relational REST framework
95 | + [hamcrest-json](https://github.com/hertzsprung/hamcrest-json) - Hamcrest matchers for comparing JSON documents
96 | + [Mule ESB](http://www.mulesoft.org/)
97 | + [GroupDocs](http://groupdocs.com/)
98 | + [Shazam](http://www.shazam.com/)
99 | + [Thucydides](http://thucydides.net/)
100 | + [and over a thousand more](https://mvnrepository.com/artifact/org.skyscreamer/jsonassert)...
101 |
102 | * * *
103 |
104 | org.json
105 | --------
106 |
107 | As of v2, JSONAssert uses @stleary's [JSON-java](https://github.com/stleary/JSON-java) implementation of org.json, the
108 | most commonly used reference implementation for JSON in Java.
109 |
110 | Resources
111 | ---------
112 |
113 | [JavaDoc](http://jsonassert.skyscreamer.org/apidocs/index.html)
114 |
115 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.skyscreamer
6 | jsonassert
7 | 2.0-rc1
8 | jar
9 |
10 | JSONassert
11 | Write JSON unit tests in less code. Great for testing REST interfaces.
12 | https://github.com/skyscreamer/JSONassert
13 |
14 |
15 | 8
16 |
17 |
18 |
19 |
20 | The Apache Software License, Version 2.0
21 | http://www.apache.org/licenses/LICENSE-2.0.txt
22 | repo
23 |
24 |
25 |
26 | scm:git:git@github.com:skyscreamer/JSONassert.git
27 | scm:git:git@github.com:skyscreamer/JSONassert.git
28 | git@github.com:skyscreamer/JSONassert.git
29 |
30 |
31 |
32 | carterpage
33 | Carter Page
34 | carter@skyscreamer.org
35 |
36 |
37 | hertzsprung
38 | James Shaw
39 |
40 |
41 |
42 |
43 |
44 |
45 | org.json
46 | json
47 | 20240303
48 |
49 |
50 | junit
51 | junit
52 | 4.13.2
53 | test
54 |
55 |
56 | org.hamcrest
57 | hamcrest
58 | 2.2
59 | test
60 |
61 |
62 |
63 |
64 |
65 |
66 | org.apache.maven.plugins
67 | maven-compiler-plugin
68 | 3.11.0
69 |
70 |
71 | org.sonatype.plugins
72 | nexus-staging-maven-plugin
73 | 1.6.7
74 | true
75 |
76 | ossrh
77 | https://oss.sonatype.org/
78 | false
79 |
80 |
81 |
82 | com.thoughtworks.xstream
83 | xstream
84 | 1.4.15
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | github-project-site
94 | gitsite:git@github.com/skyscreamer/JSONassert.git
95 |
96 |
97 | ossrh
98 | https://oss.sonatype.org/content/repositories/snapshots
99 |
100 |
101 |
102 |
103 |
104 | deploy
105 |
106 |
107 |
108 | org.apache.maven.plugins
109 | maven-source-plugin
110 | 2.2.1
111 |
112 |
113 | attach-sources
114 |
115 | jar-no-fork
116 |
117 |
118 |
119 |
120 |
121 | org.apache.maven.plugins
122 | maven-javadoc-plugin
123 | 2.9.1
124 |
125 |
126 | attach-javadocs
127 |
128 | jar
129 |
130 |
131 |
132 |
133 | ${java.home}/bin/javadoc
134 | ${maven.compiler.release}
135 |
136 |
137 |
138 | org.apache.maven.plugins
139 | maven-gpg-plugin
140 | 1.5
141 |
142 |
143 | sign-artifacts
144 | verify
145 |
146 | sign
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/src/main/java/org/skyscreamer/jsonassert/ArrayValueMatcher.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert;
16 |
17 | import java.text.MessageFormat;
18 |
19 | import org.json.JSONArray;
20 | import org.json.JSONException;
21 | import org.skyscreamer.jsonassert.comparator.JSONComparator;
22 |
23 | /**
24 | *
A value matcher for arrays. This operates like STRICT_ORDER array match,
25 | * however if expected array has less elements than actual array the matching
26 | * process loops through the expected array to get expected elements for the
27 | * additional actual elements. In general the expected array will contain a
28 | * single element which is matched against each actual array element in turn.
29 | * This allows simple verification of constant array element components and
30 | * coupled with RegularExpressionValueMatcher can be used to match specific
31 | * array element components against a regular expression pattern. As a convenience to reduce syntactic complexity of expected string, if the
32 | * expected object is not an array, a one element expected array is created
33 | * containing whatever is provided as the expected value.
34 | *
35 | *
Some examples of typical usage idioms listed below.
36 | *
37 | *
Assuming JSON to be verified is held in String variable ARRAY_OF_JSONOBJECTS and contains:
To verify that the 'id' attribute of first element of array 'a' is '1':
49 | *
50 | *
{@code
51 | * JSONComparator comparator = new DefaultComparator(JSONCompareMode.LENIENT);
52 | * Customization customization = new Customization("a", new ArrayValueMatcher
56 | *
57 | *
To simplify complexity of expected JSON string, the value "a:[{id:1}]}" may be replaced by "a:{id:1}}"
58 | *
59 | *
To verify that the 'type' attribute of second and third elements of array 'a' is 'row':
60 | *
61 | *
{@code
62 | * JSONComparator comparator = new DefaultComparator(JSONCompareMode.LENIENT);
63 | * Customization customization = new Customization("a", new ArrayValueMatcher
67 | *
68 | *
To verify that the 'type' attribute of every element of array 'a' is 'row':
69 | *
70 | *
{@code
71 | * JSONComparator comparator = new DefaultComparator(JSONCompareMode.LENIENT);
72 | * Customization customization = new Customization("a", new ArrayValueMatcher
76 | *
77 | *
To verify that the 'id' attribute of every element of array 'a' matches regular expression '\d+'. This requires a custom comparator to specify regular expression to be used to validate each array element, hence the array of Customization instances:
78 | *
79 | *
{@code
80 | * // get length of array we will verify
81 | * int aLength = ((JSONArray)((JSONObject)JSONParser.parseJSON(ARRAY_OF_JSONOBJECTS)).get("a")).length();
82 | * // create array of customizations one for each array element
83 | * RegularExpressionValueMatcher
97 | *
98 | *
To verify that the 'background' attribute of every element of array 'a' alternates between 'white' and 'grey' starting with first element 'background' being 'white':
99 | *
100 | *
{@code
101 | * JSONComparator comparator = new DefaultComparator(JSONCompareMode.LENIENT);
102 | * Customization customization = new Customization("a", new ArrayValueMatcher(comparator));
103 | * JSONAssert.assertEquals("{a:[{background:white},{background:grey}]}", ARRAY_OF_JSONOBJECTS,
104 | * new CustomComparator(JSONCompareMode.LENIENT, customization));
105 | * }
106 | *
107 | *
Assuming JSON to be verified is held in String variable ARRAY_OF_JSONARRAYS and contains:
To verify that the first three elements of JSON array 'a' are JSON arrays of length 3:
114 | *
115 | *
{@code
116 | * JSONComparator comparator = new ArraySizeComparator(JSONCompareMode.STRICT_ORDER);
117 | * Customization customization = new Customization("a", new ArrayValueMatcher(comparator, 0, 2));
118 | * JSONAssert.assertEquals("{a:[[3]]}", ARRAY_OF_JSONARRAYS, new CustomComparator(JSONCompareMode.LENIENT, customization));
119 | * }
120 | *
121 | *
NOTE: simplified expected JSON strings are not possible in this case as ArraySizeComparator does not support them.
122 | *
123 | *
To verify that the second elements of JSON array 'a' is a JSON array whose first element has the value 9:
124 | *
125 | *
{@code
126 | * JSONComparator innerComparator = new DefaultComparator(JSONCompareMode.LENIENT);
127 | * Customization innerCustomization = new Customization("a[1]", new ArrayValueMatcher(innerComparator, 0));
128 | * JSONComparator comparator = new CustomComparator(JSONCompareMode.LENIENT, innerCustomization);
129 | * Customization customization = new Customization("a", new ArrayValueMatcher(comparator, 1));
130 | * JSONAssert.assertEquals("{a:[[9]]}", ARRAY_OF_JSONARRAYS, new CustomComparator(JSONCompareMode.LENIENT, customization));
131 | * }
132 | *
133 | *
To simplify complexity of expected JSON string, the value "{a:[[9]]}" may be replaced by "{a:[9]}" or "{a:9}"
134 | *
135 | * @author Duncan Mackinder
136 | * @param Array Type
137 | */
138 | public class ArrayValueMatcher implements LocationAwareValueMatcher {
139 | private final JSONComparator comparator;
140 | private final int from;
141 | private final int to;
142 |
143 | /**
144 | * Create ArrayValueMatcher to match every element in actual array against
145 | * elements taken in sequence from expected array, repeating from start of
146 | * expected array if necessary.
147 | *
148 | * @param comparator
149 | * comparator to use to compare elements
150 | */
151 | public ArrayValueMatcher(JSONComparator comparator) {
152 | this(comparator, 0, Integer.MAX_VALUE);
153 | }
154 |
155 | /**
156 | * Create ArrayValueMatcher to match specified element in actual array
157 | * against first element of expected array.
158 | *
159 | * @param comparator
160 | * comparator to use to compare elements
161 | * @param index
162 | * index of the array element to be compared
163 | */
164 | public ArrayValueMatcher(JSONComparator comparator, int index) {
165 | this(comparator, index, index);
166 | }
167 |
168 | /**
169 | * Create ArrayValueMatcher to match every element in specified range
170 | * (inclusive) from actual array against elements taken in sequence from
171 | * expected array, repeating from start of expected array if necessary.
172 | *
173 | * @param comparator
174 | * comparator to use to compare elements
175 | * @param from first element in actual array to compared
176 | * @param to last element in actual array to compared
177 | */
178 | public ArrayValueMatcher(JSONComparator comparator, int from, int to) {
179 | assert comparator != null : "comparator null";
180 | assert from >= 0 : MessageFormat.format("from({0}) < 0", from);
181 | assert to >= from : MessageFormat.format("to({0}) < from({1})", to,
182 | from);
183 | this.comparator = comparator;
184 | this.from = from;
185 | this.to = to;
186 | }
187 |
188 | @Override
189 | /*
190 | * NOTE: method defined as required by ValueMatcher interface but will never
191 | * be called so defined simply to indicate match failure
192 | */
193 | public boolean equal(T o1, T o2) {
194 | return false;
195 | }
196 |
197 | @Override
198 | public boolean equal(String prefix, T actual, T expected, JSONCompareResult result) {
199 | if (!(actual instanceof JSONArray)) {
200 | throw new IllegalArgumentException("ArrayValueMatcher applied to non-array actual value");
201 | }
202 | try {
203 | JSONArray actualArray = (JSONArray) actual;
204 | JSONArray expectedArray = expected instanceof JSONArray ? (JSONArray) expected: new JSONArray(new Object[] { expected });
205 | int first = Math.max(0, from);
206 | int last = Math.min(actualArray.length() - 1, to);
207 | int expectedLen = expectedArray.length();
208 | for (int i = first; i <= last; i++) {
209 | String elementPrefix = MessageFormat.format("{0}[{1}]", prefix, i);
210 | Object actualElement = actualArray.get(i);
211 | Object expectedElement = expectedArray.get((i - first) % expectedLen);
212 | comparator.compareValues(elementPrefix, expectedElement, actualElement, result);
213 | }
214 | // any failures have already been passed to result, so return true
215 | return true;
216 | }
217 | catch (JSONException e) {
218 | return false;
219 | }
220 | }
221 |
222 | }
223 |
--------------------------------------------------------------------------------
/src/main/java/org/skyscreamer/jsonassert/Customization.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert;
16 |
17 | import java.util.regex.Pattern;
18 |
19 | /**
20 | * Associates a custom matcher to a specific jsonpath.
21 | */
22 | public final class Customization {
23 | private final Pattern path;
24 | private final ValueMatcher comparator;
25 |
26 | public Customization(String path, ValueMatcher comparator) {
27 | assert path != null;
28 | assert comparator != null;
29 | this.path = Pattern.compile(buildPattern(path));
30 | this.comparator = comparator;
31 | }
32 |
33 | private String buildPattern(String path) {
34 | return buildPatternLevel1(path);
35 | }
36 |
37 | private String buildPatternLevel1(String path) {
38 | String regex = "\\*\\*\\.";
39 | String replacement = "(?:.+\\.)?";
40 |
41 | return buildPattern(path, regex, replacement, 1);
42 | }
43 |
44 | private String buildPatternLevel2(String s) {
45 | if (s.isEmpty()) {
46 | return "";
47 | }
48 | String regex = "\\*\\*";
49 | String replacement = ".+";
50 |
51 | return buildPattern(s, regex, replacement, 2);
52 | }
53 |
54 | private String buildPatternLevel3(String s) {
55 | if (s.isEmpty()) {
56 | return "";
57 | }
58 |
59 | String regex = "\\*";
60 | String replacement = "[^\\.]+";
61 |
62 | return buildPattern(s, regex, replacement, 3);
63 | }
64 |
65 | private String buildPattern(String path, String regex, String replacement, int level) {
66 | StringBuilder sb = new StringBuilder();
67 | String[] parts = path.split(regex);
68 | for (int i = 0; i < parts.length; i++) {
69 | sb.append(buildPatternForLevel(level, parts[i]));
70 | if (i < parts.length - 1) {
71 | sb.append(replacement);
72 | }
73 | }
74 | return sb.toString();
75 | }
76 |
77 | private String buildPatternForLevel(int level, String part) {
78 | switch (level) {
79 | case 1:
80 | return buildPatternLevel2(part);
81 | case 2:
82 | return buildPatternLevel3(part);
83 | case 3:
84 | return Pattern.quote(part);
85 | default:
86 | return "Incorrect level.";
87 | }
88 | }
89 |
90 | /**
91 | * Creates a new {@link Customization} instance for {@code path} and {@code comparator}.
92 | *
93 | * @param path the json path
94 | * @param comparator the comparator
95 | * @return a new Customization
96 | */
97 | public static Customization customization(String path, ValueMatcher comparator) {
98 | return new Customization(path, comparator);
99 | }
100 |
101 | public boolean appliesToPath(String path) {
102 | return this.path.matcher(path).matches();
103 | }
104 |
105 | /**
106 | * Return true if actual value matches expected value using this
107 | * Customization's comparator. Calls to this method should be replaced by
108 | * calls to matches(String prefix, Object actual, Object expected,
109 | * JSONCompareResult result).
110 | *
111 | * @param actual
112 | * JSON value being tested
113 | * @param expected
114 | * expected JSON value
115 | * @return true if actual value matches expected value
116 | */
117 | @Deprecated
118 | public boolean matches(Object actual, Object expected) {
119 | return comparator.equal(actual, expected);
120 | }
121 |
122 | /**
123 | * Return true if actual value matches expected value using this
124 | * Customization's comparator. The equal method used for comparison depends
125 | * on type of comparator.
126 | *
127 | * @param prefix
128 | * JSON path of the JSON item being tested (only used if
129 | * comparator is a LocationAwareValueMatcher)
130 | * @param actual
131 | * JSON value being tested
132 | * @param expected
133 | * expected JSON value
134 | * @param result
135 | * JSONCompareResult to which match failure may be passed (only
136 | * used if comparator is a LocationAwareValueMatcher)
137 | * @return true if expected and actual equal or any difference has already
138 | * been passed to specified result instance, false otherwise.
139 | * @throws ValueMatcherException
140 | * if expected and actual values not equal and ValueMatcher
141 | * needs to override default comparison failure message that
142 | * would be generated if this method returned false.
143 | */
144 | public boolean matches(String prefix, Object actual, Object expected,
145 | JSONCompareResult result) throws ValueMatcherException {
146 | if (comparator instanceof LocationAwareValueMatcher) {
147 | return ((LocationAwareValueMatcher)comparator).equal(prefix, actual, expected, result);
148 | }
149 | return comparator.equal(actual, expected);
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/src/main/java/org/skyscreamer/jsonassert/FieldComparisonFailure.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert;
16 |
17 | /**
18 | * Models a failure when comparing two fields.
19 | */
20 | public class FieldComparisonFailure {
21 | private final String _field;
22 | private final Object _expected;
23 | private final Object _actual;
24 |
25 | public FieldComparisonFailure(String field, Object expected, Object actual) {
26 | this._field = field;
27 | this._expected = expected;
28 | this._actual = actual;
29 | }
30 |
31 | public String getField() {
32 | return _field;
33 | }
34 |
35 | public Object getExpected() {
36 | return _expected;
37 | }
38 |
39 | public Object getActual() {
40 | return _actual;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/org/skyscreamer/jsonassert/JSONAssert.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert;
16 |
17 | import org.json.JSONArray;
18 | import org.json.JSONObject;
19 | import org.skyscreamer.jsonassert.comparator.JSONComparator;
20 |
21 | /**
22 | *
A set of assertion methods useful for writing tests methods that return JSON.
23 | *
24 | *
There are two modes, strict and non-strict. In most cases, you will probably want
25 | * to set strict to false, since that will make the tests less brittle.
26 | *
27 | *
Strict tests require all of the elements requested to be returned, and only those elements
28 | * (ie, the tests are non-extensible). Arrays of elements must be returned in the same
29 | * order as expected. For example, say I'm expecting:
This library uses org.json. It has fewer dependencies than other JSON libraries (like net.sf.json),
38 | * making JSONassert more portable.
39 | *
40 | *
There are two known issues when dealing with non-strict comparisons:
41 | *
42 | *
Unless the order is strict, checking does not handle mixed types in the JSONArray
43 | * (e.g. [1,2,{a:"b"}] or [{pet:"cat"},{car:"Ford"}])
44 | *
Unless the order is strict, checking cannot handle arrays of arrays (e.g. [[1,2],[3,4]])
45 | *
46 | *
You do not have to worry about encountering a false positive or false negative in these two edge cases.
47 | * JSONassert will identify the conditions and throw a descriptive {@link IllegalArgumentException}. These
48 | * cases will be fixed in future versions.
49 | *
50 | */
51 | public class JSONAssert {
52 | private JSONAssert() {}
53 |
54 | /**
55 | * Asserts that the JSONObject provided matches the expected string. If it isn't it throws an
56 | * {@link AssertionError}.
57 | *
58 | * @param expectedStr Expected JSON string
59 | * @param actual JSONObject to compare
60 | * @param strict Enables strict checking
61 | */
62 | public static void assertEquals(String expectedStr, JSONObject actual, boolean strict) {
63 | assertEquals(expectedStr, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
64 | }
65 |
66 | /**
67 | * Asserts that the JSONObject provided matches the expected string. If it isn't it throws an
68 | * {@link AssertionError}.
69 | *
70 | * @param message Error message to be displayed in case of assertion failure
71 | * @param expectedStr Expected JSON string
72 | * @param actual JSONObject to compare
73 | * @param strict Enables strict checking
74 | */
75 | public static void assertEquals(String message, String expectedStr, JSONObject actual, boolean strict) {
76 | assertEquals(message, expectedStr, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
77 | }
78 |
79 | /**
80 | * Asserts that the JSONObject provided does not match the expected string. If it is it throws an
81 | * {@link AssertionError}.
82 | *
83 | * @see #assertEquals(String, JSONObject, boolean)
84 | *
85 | * @param expectedStr Expected JSON string
86 | * @param actual JSONObject to compare
87 | * @param strict Enables strict checking
88 | */
89 | public static void assertNotEquals(String expectedStr, JSONObject actual, boolean strict) {
90 | assertNotEquals(expectedStr, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
91 | }
92 |
93 | /**
94 | * Asserts that the JSONObject provided does not match the expected string. If it is it throws an
95 | * {@link AssertionError}.
96 | *
97 | * @see #assertEquals(String, JSONObject, boolean)
98 | *
99 | * @param message Error message to be displayed in case of assertion failure
100 | * @param expectedStr Expected JSON string
101 | * @param actual JSONObject to compare
102 | * @param strict Enables strict checking
103 | */
104 | public static void assertNotEquals(String message, String expectedStr, JSONObject actual, boolean strict) {
105 | assertNotEquals(message, expectedStr, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
106 | }
107 |
108 | /**
109 | * Asserts that the JSONObject provided matches the expected string. If it isn't it throws an
110 | * {@link AssertionError}.
111 | *
112 | * @param expectedStr Expected JSON string
113 | * @param actual JSONObject to compare
114 | * @param compareMode Specifies which comparison mode to use
115 | */
116 | public static void assertEquals(String expectedStr, JSONObject actual, JSONCompareMode compareMode) {
117 | assertEquals("", expectedStr, actual, compareMode);
118 | }
119 |
120 | /**
121 | * Asserts that the JSONObject provided matches the expected string. If it isn't it throws an
122 | * {@link AssertionError}.
123 | *
124 | * @param message Error message to be displayed in case of assertion failure
125 | * @param expectedStr Expected JSON string
126 | * @param actual JSONObject to compare
127 | * @param compareMode Specifies which comparison mode to use
128 | */
129 | public static void assertEquals(String message, String expectedStr, JSONObject actual, JSONCompareMode compareMode)
130 | {
131 | Object expected = JSONParser.parseJSON(expectedStr);
132 | if (expected instanceof JSONObject) {
133 | assertEquals(message, (JSONObject)expected, actual, compareMode);
134 | }
135 | else {
136 | throw new AssertionError("Expecting a JSON array, but passing in a JSON object");
137 | }
138 | }
139 |
140 | /**
141 | * Asserts that the JSONObject provided does not match the expected string. If it is it throws an
142 | * {@link AssertionError}.
143 | *
144 | * @see #assertEquals(String, JSONObject, JSONCompareMode)
145 | *
146 | * @param expectedStr Expected JSON string
147 | * @param actual JSONObject to compare
148 | * @param compareMode Specifies which comparison mode to use
149 | */
150 | public static void assertNotEquals(String expectedStr, JSONObject actual, JSONCompareMode compareMode) {
151 | assertNotEquals("", expectedStr, actual, compareMode);
152 | }
153 |
154 | /**
155 | * Asserts that the JSONObject provided does not match the expected string. If it is it throws an
156 | * {@link AssertionError}.
157 | *
158 | * @see #assertEquals(String, JSONObject, JSONCompareMode)
159 | *
160 | * @param message Error message to be displayed in case of assertion failure
161 | * @param expectedStr Expected JSON string
162 | * @param actual JSONObject to compare
163 | * @param compareMode Specifies which comparison mode to use
164 | */
165 | public static void assertNotEquals(String message, String expectedStr, JSONObject actual,
166 | JSONCompareMode compareMode) {
167 | Object expected = JSONParser.parseJSON(expectedStr);
168 | if (expected instanceof JSONObject) {
169 | assertNotEquals(message, (JSONObject) expected, actual, compareMode);
170 | }
171 | else {
172 | throw new AssertionError("Expecting a JSON array, but passing in a JSON object");
173 | }
174 | }
175 |
176 | /**
177 | * Asserts that the JSONArray provided matches the expected string. If it isn't it throws an
178 | * {@link AssertionError}.
179 | *
180 | * @param expectedStr Expected JSON string
181 | * @param actual JSONArray to compare
182 | * @param strict Enables strict checking
183 | */
184 | public static void assertEquals(String expectedStr, JSONArray actual, boolean strict) {
185 | assertEquals(expectedStr, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
186 | }
187 |
188 | /**
189 | * Asserts that the JSONArray provided matches the expected string. If it isn't it throws an
190 | * {@link AssertionError}.
191 | *
192 | * @param message Error message to be displayed in case of assertion failure
193 | * @param expectedStr Expected JSON string
194 | * @param actual JSONArray to compare
195 | * @param strict Enables strict checking
196 | */
197 | public static void assertEquals(String message, String expectedStr, JSONArray actual, boolean strict) {
198 | assertEquals(message, expectedStr, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
199 | }
200 |
201 | /**
202 | * Asserts that the JSONArray provided does not match the expected string. If it is it throws an
203 | * {@link AssertionError}.
204 | *
205 | * @param expectedStr Expected JSON string
206 | * @param actual JSONArray to compare
207 | * @param strict Enables strict checking
208 | */
209 | public static void assertNotEquals(String expectedStr, JSONArray actual, boolean strict) {
210 | assertNotEquals(expectedStr, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
211 | }
212 |
213 | /**
214 | * Asserts that the JSONArray provided does not match the expected string. If it is it throws an
215 | * {@link AssertionError}.
216 | *
217 | * @param message Error message to be displayed in case of assertion failure
218 | * @param expectedStr Expected JSON string
219 | * @param actual JSONArray to compare
220 | * @param strict Enables strict checking
221 | */
222 | public static void assertNotEquals(String message, String expectedStr, JSONArray actual, boolean strict) {
223 | assertNotEquals(message, expectedStr, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
224 | }
225 |
226 | /**
227 | * Asserts that the JSONArray provided matches the expected string. If it isn't it throws an
228 | * {@link AssertionError}.
229 | *
230 | * @param expectedStr Expected JSON string
231 | * @param actual JSONArray to compare
232 | * @param compareMode Specifies which comparison mode to use
233 | */
234 | public static void assertEquals(String expectedStr, JSONArray actual, JSONCompareMode compareMode) {
235 | assertEquals("", expectedStr, actual, compareMode);
236 | }
237 |
238 | /**
239 | * Asserts that the JSONArray provided matches the expected string. If it isn't it throws an
240 | * {@link AssertionError}.
241 | *
242 | * @param message Error message to be displayed in case of assertion failure
243 | * @param expectedStr Expected JSON string
244 | * @param actual JSONArray to compare
245 | * @param compareMode Specifies which comparison mode to use
246 | */
247 | public static void assertEquals(String message, String expectedStr, JSONArray actual, JSONCompareMode compareMode) {
248 | Object expected = JSONParser.parseJSON(expectedStr);
249 | if (expected instanceof JSONArray) {
250 | assertEquals(message, (JSONArray) expected, actual, compareMode);
251 | }
252 | else {
253 | throw new AssertionError("Expecting a JSON object, but passing in a JSON array");
254 | }
255 | }
256 |
257 | /**
258 | * Asserts that the JSONArray provided does not match the expected string. If it is it throws an
259 | * {@link AssertionError}.
260 | *
261 | * @param expectedStr Expected JSON string
262 | * @param actual JSONArray to compare
263 | * @param compareMode Specifies which comparison mode to use
264 | */
265 | public static void assertNotEquals(String expectedStr, JSONArray actual, JSONCompareMode compareMode) {
266 | Object expected = JSONParser.parseJSON(expectedStr);
267 | if (expected instanceof JSONArray) {
268 | assertNotEquals((JSONArray) expected, actual, compareMode);
269 | }
270 | else {
271 | throw new AssertionError("Expecting a JSON object, but passing in a JSON array");
272 | }
273 | }
274 |
275 | /**
276 | * Asserts that the JSONArray provided does not match the expected string. If it is it throws an
277 | * {@link AssertionError}.
278 | *
279 | * @param message Error message to be displayed in case of assertion failure
280 | * @param expectedStr Expected JSON string
281 | * @param actual JSONArray to compare
282 | * @param compareMode Specifies which comparison mode to use
283 | */
284 | public static void assertNotEquals(String message, String expectedStr, JSONArray actual,
285 | JSONCompareMode compareMode) {
286 | Object expected = JSONParser.parseJSON(expectedStr);
287 | if (expected instanceof JSONArray) {
288 | assertNotEquals(message, (JSONArray) expected, actual, compareMode);
289 | }
290 | else {
291 | throw new AssertionError("Expecting a JSON object, but passing in a JSON array");
292 | }
293 | }
294 |
295 | /**
296 | * Asserts that the JSONArray provided matches the expected string. If it isn't it throws an
297 | * {@link AssertionError}.
298 | *
299 | * @param expectedStr Expected JSON string
300 | * @param actualStr String to compare
301 | * @param strict Enables strict checking
302 | */
303 | public static void assertEquals(String expectedStr, String actualStr, boolean strict) {
304 | assertEquals(expectedStr, actualStr, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
305 | }
306 |
307 | /**
308 | * Asserts that the JSONArray provided matches the expected string. If it isn't it throws an
309 | * {@link AssertionError}.
310 | *
311 | * @param message Error message to be displayed in case of assertion failure
312 | * @param expectedStr Expected JSON string
313 | * @param actualStr String to compare
314 | * @param strict Enables strict checking
315 | */
316 | public static void assertEquals(String message, String expectedStr, String actualStr, boolean strict) {
317 | assertEquals(message, expectedStr, actualStr, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
318 | }
319 |
320 | /**
321 | * Asserts that the JSONArray provided does not match the expected string. If it is it throws an
322 | * {@link AssertionError}.
323 | *
324 | * @param expectedStr Expected JSON string
325 | * @param actualStr String to compare
326 | * @param strict Enables strict checking
327 | */
328 | public static void assertNotEquals(String expectedStr, String actualStr, boolean strict) {
329 | assertNotEquals(expectedStr, actualStr, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
330 | }
331 |
332 | /**
333 | * Asserts that the JSONArray provided does not match the expected string. If it is it throws an
334 | * {@link AssertionError}.
335 | *
336 | * @param message Error message to be displayed in case of assertion failure
337 | * @param expectedStr Expected JSON string
338 | * @param actualStr String to compare
339 | * @param strict Enables strict checking
340 | */
341 | public static void assertNotEquals(String message, String expectedStr, String actualStr, boolean strict) {
342 | assertNotEquals(message, expectedStr, actualStr, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
343 | }
344 |
345 | /**
346 | * Asserts that the JSONArray provided matches the expected string. If it isn't it throws an
347 | * {@link AssertionError}.
348 | *
349 | * @param expectedStr Expected JSON string
350 | * @param actualStr String to compare
351 | * @param compareMode Specifies which comparison mode to use
352 | */
353 | public static void assertEquals(String expectedStr, String actualStr, JSONCompareMode compareMode) {
354 | assertEquals("", expectedStr, actualStr, compareMode);
355 | }
356 |
357 | /**
358 | * Asserts that the JSONArray provided matches the expected string. If it isn't it throws an
359 | * {@link AssertionError}.
360 | *
361 | * @param message Error message to be displayed in case of assertion failure
362 | * @param expectedStr Expected JSON string
363 | * @param actualStr String to compare
364 | * @param compareMode Specifies which comparison mode to use
365 | */
366 | public static void assertEquals(String message, String expectedStr, String actualStr, JSONCompareMode compareMode) {
367 | if (expectedStr==actualStr) return;
368 | if (expectedStr==null){
369 | throw new AssertionError("Expected string is null.");
370 | }else if (actualStr==null){
371 | throw new AssertionError("Actual string is null.");
372 | }
373 | JSONCompareResult result = JSONCompare.compareJSON(expectedStr, actualStr, compareMode);
374 | if (result.failed()) {
375 | throw new AssertionError(getCombinedMessage(message, result.getMessage()));
376 | }
377 | }
378 |
379 | /**
380 | * Asserts that the JSONArray provided does not match the expected string. If it is it throws an
381 | * {@link AssertionError}.
382 | *
383 | * @param expectedStr Expected JSON string
384 | * @param actualStr String to compare
385 | * @param compareMode Specifies which comparison mode to use
386 | */
387 | public static void assertNotEquals(String expectedStr, String actualStr, JSONCompareMode compareMode) {
388 | assertNotEquals("", expectedStr, actualStr, compareMode);
389 | }
390 |
391 | /**
392 | * Asserts that the JSONArray provided does not match the expected string. If it is it throws an
393 | * {@link AssertionError}.
394 | *
395 | * @param message Error message to be displayed in case of assertion failure
396 | * @param expectedStr Expected JSON string
397 | * @param actualStr String to compare
398 | * @param compareMode Specifies which comparison mode to use
399 | */
400 | public static void assertNotEquals(String message, String expectedStr, String actualStr,
401 | JSONCompareMode compareMode) {
402 | JSONCompareResult result = JSONCompare.compareJSON(expectedStr, actualStr, compareMode);
403 | if (result.passed()) {
404 | throw new AssertionError(getCombinedMessage(message, result.getMessage()));
405 | }
406 | }
407 |
408 | /**
409 | * Asserts that the json string provided matches the expected string. If it isn't it throws an
410 | * {@link AssertionError}.
411 | *
412 | * @param expectedStr Expected JSON string
413 | * @param actualStr String to compare
414 | * @param comparator Comparator
415 | */
416 | public static void assertEquals(String expectedStr, String actualStr, JSONComparator comparator) {
417 | assertEquals("", expectedStr, actualStr, comparator);
418 |
419 | }
420 |
421 | /**
422 | * Asserts that the json string provided matches the expected string. If it isn't it throws an
423 | * {@link AssertionError}.
424 | *
425 | * @param message Error message to be displayed in case of assertion failure
426 | * @param expectedStr Expected JSON string
427 | * @param actualStr String to compare
428 | * @param comparator Comparator
429 | */
430 | public static void assertEquals(String message, String expectedStr, String actualStr, JSONComparator comparator) {
431 | JSONCompareResult result = JSONCompare.compareJSON(expectedStr, actualStr, comparator);
432 | if (result.failed()) {
433 | throw new AssertionError(getCombinedMessage(message, result.getMessage()));
434 | }
435 | }
436 |
437 | /**
438 | * Asserts that the json string provided does not match the expected string. If it is it throws an
439 | * {@link AssertionError}.
440 | *
441 | * @param expectedStr Expected JSON string
442 | * @param actualStr String to compare
443 | * @param comparator Comparator
444 | */
445 | public static void assertNotEquals(String expectedStr, String actualStr, JSONComparator comparator) {
446 | assertNotEquals("", expectedStr, actualStr, comparator);
447 | }
448 |
449 | /**
450 | * Asserts that the json string provided does not match the expected string. If it is it throws an
451 | * {@link AssertionError}.
452 | *
453 | * @param message Error message to be displayed in case of assertion failure
454 | * @param expectedStr Expected JSON string
455 | * @param actualStr String to compare
456 | * @param comparator Comparator
457 | */
458 | public static void assertNotEquals(String message, String expectedStr, String actualStr,
459 | JSONComparator comparator) {
460 | JSONCompareResult result = JSONCompare.compareJSON(expectedStr, actualStr, comparator);
461 | if (result.passed()) {
462 | throw new AssertionError(getCombinedMessage(message, result.getMessage()));
463 | }
464 | }
465 |
466 | /**
467 | * Asserts that the JSONObject provided matches the expected JSONObject. If it isn't it throws an
468 | * {@link AssertionError}.
469 | *
470 | * @param expected Expected JSONObject
471 | * @param actual JSONObject to compare
472 | * @param comparator Comparator
473 | */
474 | public static void assertEquals(JSONObject expected, JSONObject actual, JSONComparator comparator) {
475 | assertEquals("", expected, actual, comparator);
476 | }
477 |
478 | /**
479 | * Asserts that the JSONObject provided matches the expected JSONObject. If it isn't it throws an
480 | * {@link AssertionError}.
481 | *
482 | * @param message Error message to be displayed in case of assertion failure
483 | * @param expected Expected JSONObject
484 | * @param actual JSONObject to compare
485 | * @param comparator Comparator
486 | */
487 | public static void assertEquals(String message, JSONObject expected, JSONObject actual, JSONComparator comparator) {
488 | JSONCompareResult result = JSONCompare.compareJSON(expected, actual, comparator);
489 | if (result.failed()) {
490 | throw new AssertionError(getCombinedMessage(message, result.getMessage()));
491 | }
492 | }
493 |
494 | /**
495 | * Asserts that the JSONObject provided does not match the expected JSONObject. If it is it throws an
496 | * {@link AssertionError}.
497 | *
498 | * @param expected Expected JSONObject
499 | * @param actual JSONObject to compare
500 | * @param comparator Comparator
501 | */
502 | public static void assertNotEquals(JSONObject expected, JSONObject actual, JSONComparator comparator) {
503 | assertNotEquals("", expected, actual, comparator);
504 | }
505 |
506 | /**
507 | * Asserts that the JSONObject provided does not match the expected JSONObject. If it is it throws an
508 | * {@link AssertionError}.
509 | *
510 | * @param message Error message to be displayed in case of assertion failure
511 | * @param expected Expected JSONObject
512 | * @param actual JSONObject to compare
513 | * @param comparator Comparator
514 | */
515 | public static void assertNotEquals(String message, JSONObject expected, JSONObject actual,
516 | JSONComparator comparator) {
517 | JSONCompareResult result = JSONCompare.compareJSON(expected, actual, comparator);
518 | if (result.passed()) {
519 | throw new AssertionError(getCombinedMessage(message, result.getMessage()));
520 | }
521 | }
522 |
523 | /**
524 | * Asserts that the JSONObject provided matches the expected JSONObject. If it isn't it throws an
525 | * {@link AssertionError}.
526 | *
527 | * @param expected Expected JSONObject
528 | * @param actual JSONObject to compare
529 | * @param strict Enables strict checking
530 | */
531 | public static void assertEquals(JSONObject expected, JSONObject actual, boolean strict) {
532 | assertEquals(expected, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
533 | }
534 |
535 | /**
536 | * Asserts that the JSONObject provided matches the expected JSONObject. If it isn't it throws an
537 | * {@link AssertionError}.
538 | *
539 | * @param message Error message to be displayed in case of assertion failure
540 | * @param expected Expected JSONObject
541 | * @param actual JSONObject to compare
542 | * @param strict Enables strict checking
543 | */
544 | public static void assertEquals(String message, JSONObject expected, JSONObject actual, boolean strict) {
545 | assertEquals(message, expected, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
546 | }
547 |
548 | /**
549 | * Asserts that the JSONObject provided does not match the expected JSONObject. If it is it throws an
550 | * {@link AssertionError}.
551 | *
552 | * @param expected Expected JSONObject
553 | * @param actual JSONObject to compare
554 | * @param strict Enables strict checking
555 | */
556 | public static void assertNotEquals(JSONObject expected, JSONObject actual, boolean strict) {
557 | assertNotEquals(expected, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
558 | }
559 |
560 | /**
561 | * Asserts that the JSONObject provided does not match the expected JSONObject. If it is it throws an
562 | * {@link AssertionError}.
563 | *
564 | * @param message Error message to be displayed in case of assertion failure
565 | * @param expected Expected JSONObject
566 | * @param actual JSONObject to compare
567 | * @param strict Enables strict checking
568 | */
569 | public static void assertNotEquals(String message, JSONObject expected, JSONObject actual, boolean strict) {
570 | assertNotEquals(message, expected, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
571 | }
572 |
573 | /**
574 | * Asserts that the JSONObject provided matches the expected JSONObject. If it isn't it throws an
575 | * {@link AssertionError}.
576 | *
577 | * @param expected Expected JSONObject
578 | * @param actual JSONObject to compare
579 | * @param compareMode Specifies which comparison mode to use
580 | */
581 | public static void assertEquals(JSONObject expected, JSONObject actual, JSONCompareMode compareMode) {
582 | assertEquals("", expected, actual, compareMode);
583 | }
584 |
585 | /**
586 | * Asserts that the JSONObject provided matches the expected JSONObject. If it isn't it throws an
587 | * {@link AssertionError}.
588 | *
589 | * @param message Error message to be displayed in case of assertion failure
590 | * @param expected Expected JSONObject
591 | * @param actual JSONObject to compare
592 | * @param compareMode Specifies which comparison mode to use
593 | */
594 | public static void assertEquals(String message, JSONObject expected, JSONObject actual,
595 | JSONCompareMode compareMode) {
596 | JSONCompareResult result = JSONCompare.compareJSON(expected, actual, compareMode);
597 | if (result.failed()) {
598 | throw new AssertionError(getCombinedMessage(message, result.getMessage()));
599 | }
600 | }
601 |
602 | /**
603 | * Asserts that the JSONObject provided does not match the expected JSONObject. If it is it throws an
604 | * {@link AssertionError}.
605 | *
606 | * @param expected Expected JSONObject
607 | * @param actual JSONObject to compare
608 | * @param compareMode Specifies which comparison mode to use
609 | */
610 | public static void assertNotEquals(JSONObject expected, JSONObject actual, JSONCompareMode compareMode) {
611 | assertNotEquals("", expected, actual, compareMode);
612 | }
613 |
614 | /**
615 | * Asserts that the JSONObject provided does not match the expected JSONObject. If it is it throws an
616 | * {@link AssertionError}.
617 | *
618 | * @param message Error message to be displayed in case of assertion failure
619 | * @param expected Expected JSONObject
620 | * @param actual JSONObject to compare
621 | * @param compareMode Specifies which comparison mode to use
622 | */
623 | public static void assertNotEquals(String message, JSONObject expected, JSONObject actual,
624 | JSONCompareMode compareMode) {
625 | JSONCompareResult result = JSONCompare.compareJSON(expected, actual, compareMode);
626 | if (result.passed()) {
627 | throw new AssertionError(getCombinedMessage(message, result.getMessage()));
628 | }
629 | }
630 |
631 | /**
632 | * Asserts that the JSONArray provided matches the expected JSONArray. If it isn't it throws an
633 | * {@link AssertionError}.
634 | *
635 | * @param expected Expected JSONArray
636 | * @param actual JSONArray to compare
637 | * @param strict Enables strict checking
638 | */
639 | public static void assertEquals(JSONArray expected, JSONArray actual, boolean strict) {
640 | assertEquals("", expected, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
641 | }
642 |
643 | /**
644 | * Asserts that the JSONArray provided matches the expected JSONArray. If it isn't it throws an
645 | * {@link AssertionError}.
646 | *
647 | * @param message Error message to be displayed in case of assertion failure
648 | * @param expected Expected JSONArray
649 | * @param actual JSONArray to compare
650 | * @param strict Enables strict checking
651 | */
652 | public static void assertEquals(String message, JSONArray expected, JSONArray actual, boolean strict) {
653 | assertEquals(message, expected, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
654 | }
655 |
656 | /**
657 | * Asserts that the JSONArray provided does not match the expected JSONArray. If it is it throws an
658 | * {@link AssertionError}.
659 | *
660 | * @param expected Expected JSONArray
661 | * @param actual JSONArray to compare
662 | * @param strict Enables strict checking
663 | */
664 | public static void assertNotEquals(JSONArray expected, JSONArray actual, boolean strict) {
665 | assertNotEquals(expected, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
666 | }
667 |
668 | /**
669 | * Asserts that the JSONArray provided does not match the expected JSONArray. If it is it throws an
670 | * {@link AssertionError}.
671 | *
672 | * @param message Error message to be displayed in case of assertion failure
673 | * @param expected Expected JSONArray
674 | * @param actual JSONArray to compare
675 | * @param strict Enables strict checking
676 | */
677 | public static void assertNotEquals(String message, JSONArray expected, JSONArray actual, boolean strict) {
678 | assertNotEquals(message, expected, actual, strict ? JSONCompareMode.STRICT : JSONCompareMode.LENIENT);
679 | }
680 |
681 | /**
682 | * Asserts that the JSONArray provided matches the expected JSONArray. If it isn't it throws an
683 | * {@link AssertionError}.
684 | *
685 | * @param expected Expected JSONArray
686 | * @param actual JSONArray to compare
687 | * @param compareMode Specifies which comparison mode to use
688 | */
689 | public static void assertEquals(JSONArray expected, JSONArray actual, JSONCompareMode compareMode) {
690 | assertEquals("", expected, actual, compareMode);
691 | }
692 |
693 | /**
694 | * Asserts that the JSONArray provided matches the expected JSONArray. If it isn't it throws an
695 | * {@link AssertionError}.
696 | *
697 | * @param message Error message to be displayed in case of assertion failure
698 | * @param expected Expected JSONArray
699 | * @param actual JSONArray to compare
700 | * @param compareMode Specifies which comparison mode to use
701 | */
702 | public static void assertEquals(String message, JSONArray expected, JSONArray actual, JSONCompareMode compareMode) {
703 | JSONCompareResult result = JSONCompare.compareJSON(expected, actual, compareMode);
704 | if (result.failed()) {
705 | throw new AssertionError(getCombinedMessage(message, result.getMessage()));
706 | }
707 | }
708 |
709 | /**
710 | * Asserts that the JSONArray provided does not match the expected JSONArray. If it is it throws an
711 | * {@link AssertionError}.
712 | *
713 | * @param expected Expected JSONArray
714 | * @param actual JSONArray to compare
715 | * @param compareMode Specifies which comparison mode to use
716 | */
717 | public static void assertNotEquals(JSONArray expected, JSONArray actual, JSONCompareMode compareMode) {
718 | assertNotEquals("", expected, actual, compareMode);
719 | }
720 |
721 | /**
722 | * Asserts that the JSONArray provided does not match the expected JSONArray. If it is it throws an
723 | * {@link AssertionError}.
724 | *
725 | * @param message Error message to be displayed in case of assertion failure
726 | * @param expected Expected JSONArray
727 | * @param actual JSONArray to compare
728 | * @param compareMode Specifies which comparison mode to use
729 | */
730 | public static void assertNotEquals(String message, JSONArray expected, JSONArray actual,
731 | JSONCompareMode compareMode) {
732 | JSONCompareResult result = JSONCompare.compareJSON(expected, actual, compareMode);
733 | if (result.passed()) {
734 | throw new AssertionError(getCombinedMessage(message, result.getMessage()));
735 | }
736 | }
737 |
738 | private static String getCombinedMessage(String message1, String message2) {
739 | String combinedMessage = "";
740 |
741 | if(message1 == null || "".equals(message1)) {
742 | combinedMessage = message2;
743 | } else {
744 | combinedMessage = message1 + " " + message2;
745 | }
746 | return combinedMessage;
747 | }
748 | }
749 |
--------------------------------------------------------------------------------
/src/main/java/org/skyscreamer/jsonassert/JSONCompare.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert;
16 |
17 | import org.json.JSONArray;
18 | import org.json.JSONObject;
19 | import org.json.JSONString;
20 | import org.skyscreamer.jsonassert.comparator.DefaultComparator;
21 | import org.skyscreamer.jsonassert.comparator.JSONComparator;
22 |
23 | /**
24 | * Provides API to compare two JSON entities. This is the backend to {@link JSONAssert}, but it can
25 | * be programmed against directly to access the functionality. (eg, to make something that works with a
26 | * non-JUnit test framework)
27 | */
28 | public final class JSONCompare {
29 | private JSONCompare() {
30 | }
31 |
32 | private static JSONComparator getComparatorForMode(JSONCompareMode mode) {
33 | return new DefaultComparator(mode);
34 | }
35 |
36 | /**
37 | * Compares JSON string provided to the expected JSON string using provided comparator, and returns the results of
38 | * the comparison.
39 | * @param expectedStr Expected JSON string
40 | * @param actualStr JSON string to compare
41 | * @param comparator Comparator to use
42 | * @return result of the comparison
43 | * @throws IllegalArgumentException when type of expectedStr doesn't match the type of actualStr
44 | */
45 | public static JSONCompareResult compareJSON(String expectedStr, String actualStr, JSONComparator comparator) {
46 | Object expected = JSONParser.parseJSON(expectedStr);
47 | Object actual = JSONParser.parseJSON(actualStr);
48 | if ((expected instanceof JSONObject) && (actual instanceof JSONObject)) {
49 | return compareJSON((JSONObject) expected, (JSONObject) actual, comparator);
50 | }
51 | else if ((expected instanceof JSONArray) && (actual instanceof JSONArray)) {
52 | return compareJSON((JSONArray)expected, (JSONArray)actual, comparator);
53 | }
54 | else if (expected instanceof JSONString && actual instanceof JSONString) {
55 | return compareJson((JSONString) expected, (JSONString) actual);
56 | }
57 | else if (expected instanceof JSONObject) {
58 | return new JSONCompareResult().fail("", expected, actual);
59 | }
60 | else {
61 | return new JSONCompareResult().fail("", expected, actual);
62 | }
63 | }
64 |
65 | /**
66 | * Compares JSON object provided to the expected JSON object using provided comparator, and returns the results of
67 | * the comparison.
68 | * @param expected expected json object
69 | * @param actual actual json object
70 | * @param comparator comparator to use
71 | * @return result of the comparison
72 | */
73 | public static JSONCompareResult compareJSON(JSONObject expected, JSONObject actual, JSONComparator comparator) {
74 | return comparator.compareJSON(expected, actual);
75 | }
76 |
77 | /**
78 | * Compares JSON object provided to the expected JSON object using provided comparator, and returns the results of
79 | * the comparison.
80 | * @param expected expected json array
81 | * @param actual actual json array
82 | * @param comparator comparator to use
83 | * @return result of the comparison
84 | */
85 | public static JSONCompareResult compareJSON(JSONArray expected, JSONArray actual, JSONComparator comparator) {
86 | return comparator.compareJSON(expected, actual);
87 | }
88 |
89 | /**
90 | * Compares {@link JSONString} provided to the expected {@code JSONString}, checking that the
91 | * {@link org.json.JSONString#toJSONString()} are equal.
92 | *
93 | * @param expected Expected {@code JSONstring}
94 | * @param actual {@code JSONstring} to compare
95 | * @return result of the comparison
96 | */
97 | public static JSONCompareResult compareJson(final JSONString expected, final JSONString actual) {
98 | final JSONCompareResult result = new JSONCompareResult();
99 | final String expectedJson = expected.toJSONString();
100 | final String actualJson = actual.toJSONString();
101 | if (!expectedJson.equals(actualJson)) {
102 | result.fail("");
103 | }
104 | return result;
105 | }
106 |
107 | /**
108 | * Compares JSON string provided to the expected JSON string, and returns the results of the comparison.
109 | *
110 | * @param expectedStr Expected JSON string
111 | * @param actualStr JSON string to compare
112 | * @param mode Defines comparison behavior
113 | * @return result of the comparison
114 | */
115 | public static JSONCompareResult compareJSON(String expectedStr, String actualStr, JSONCompareMode mode) {
116 | return compareJSON(expectedStr, actualStr, getComparatorForMode(mode));
117 | }
118 |
119 | /**
120 | * Compares JSONObject provided to the expected JSONObject, and returns the results of the comparison.
121 | *
122 | * @param expected Expected JSONObject
123 | * @param actual JSONObject to compare
124 | * @param mode Defines comparison behavior
125 | * @return result of the comparison
126 | */
127 | public static JSONCompareResult compareJSON(JSONObject expected, JSONObject actual, JSONCompareMode mode) {
128 | return compareJSON(expected, actual, getComparatorForMode(mode));
129 | }
130 |
131 |
132 | /**
133 | * Compares JSONArray provided to the expected JSONArray, and returns the results of the comparison.
134 | *
135 | * @param expected Expected JSONArray
136 | * @param actual JSONArray to compare
137 | * @param mode Defines comparison behavior
138 | * @return result of the comparison
139 | */
140 | public static JSONCompareResult compareJSON(JSONArray expected, JSONArray actual, JSONCompareMode mode) {
141 | return compareJSON(expected, actual, getComparatorForMode(mode));
142 | }
143 |
144 | }
145 |
--------------------------------------------------------------------------------
/src/main/java/org/skyscreamer/jsonassert/JSONCompareMode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert;
16 |
17 | /**
18 | *
These different modes define different behavior for the comparison of JSON for testing.
19 | * Each mode encapsulates two underlying behaviors: extensibility and strict ordering.
20 | *
21 | *
22 | *
23 | * Behavior of JSONCompareMode
24 | *
25 | *
Extensible
Strict Ordering
26 | *
STRICT
no
yes
27 | *
LENIENT
yes
no
28 | *
NON_EXTENSIBLE
no
no
29 | *
STRICT_ORDER
yes
yes
30 | *
31 | *
32 | *
If extensibility not allowed, then all of the expected values must match in what's being tested,
33 | * but any additional fields will cause the test to fail. When extensibility is allowed, all values
34 | * must still match. For example, if you're expecting:
35 | *
36 | * {id:1,name:"Carter"}
37 | *
38 | *
Then the following will pass when extensible, and will fail when not:
Assertion parameters can be a java.lang.String with JSON data, an org.json.JSONObject, or an org.json.JSONArray.
45 | For readability, we'll use strings in the following examples.
46 |
47 |
48 |
A really simple example. Get a JSON object and test its ID:
Because application interfaces are naturally extended as they mature, it is recommended that you
77 | default to leaving strict mode off, except in particular cases.
78 |
79 |
80 |
Arrays rules are different. If sequence is important, you can enable strict mode:
Write JSON unit tests in less code. Great for testing REST interfaces.
45 |
46 |
Code JSON tests as if you are comparing a string. Under the covers, JSONassert converts your string into a JSON object and compares the logical structure and data with the actual JSON. When strict is set to false (recommended), it forgives reordering data and extending results (as long as all the expected elements are there), making tests less brittle.
We tried to make error messages easy to understand. This is really important, since it gets hard for the eye to pick out the difference, particularly in long JSON strings. For example:
115 |
116 | ... which tells you that the pets array under the friend where id=3 was supposed to contain "bird", but had "cat" instead.
117 | (Maybe the cat ate the bird?)
118 |
119 |
120 |
121 |
122 |
Contact
123 |
124 | This is open source so if you want to help out whether by submitting code, design, suggestions, feedback,
125 | or feature requests, we appreciate whatever you can contribute. Contact us at
126 | jsonassert-dev@skyscreamer.org with questions or ideas.
127 |
It is recommended that you leave strictMode
78 | off, so your tests will be less brittle.
79 | Turn it on if you need to enforce a particular order for arrays, or if you want to
80 | ensure that the actual JSON does not have any fields beyond what's expected.
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/src/test/java/org/skyscreamer/jsonassert/ArrayValueMatcherTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert;
16 |
17 | import static org.junit.Assert.assertEquals;
18 | import static org.junit.Assert.assertTrue;
19 | import static org.junit.Assert.fail;
20 |
21 | import java.text.MessageFormat;
22 |
23 | import org.json.JSONArray;
24 | import org.json.JSONObject;
25 | import org.junit.Test;
26 | import org.skyscreamer.jsonassert.comparator.ArraySizeComparator;
27 | import org.skyscreamer.jsonassert.comparator.CustomComparator;
28 | import org.skyscreamer.jsonassert.comparator.DefaultComparator;
29 | import org.skyscreamer.jsonassert.comparator.JSONComparator;
30 |
31 | /**
32 | * Unit tests for ArrayValueMatcher
33 | *
34 | * @author Duncan Mackinder
35 | *
36 | */
37 | public class ArrayValueMatcherTest {
38 |
39 | private static final String ARRAY_OF_JSONOBJECTS = "{a:[{background:white,id:1,type:row},{background:grey,id:2,type:row},{background:white,id:3,type:row},{background:grey,id:4,type:row}]}";
40 | private static final String ARRAY_OF_INTEGERS = "{a:[1,2,3,4,5]}";
41 | private static final String ARRAY_OF_JSONARRAYS = "{a:[[6,7,8],[9,10,11],[12,13,14],[19,20,21,22]]}";
42 | private static final JSONComparator comparator = new DefaultComparator(JSONCompareMode.LENIENT);
43 |
44 | private void doTest(String jsonPath, ArrayValueMatcher arrayValueMatcher, String expectedJSON,
45 | String actualJSON) {
46 | Customization customization = new Customization(jsonPath, arrayValueMatcher);
47 | JSONAssert.assertEquals(expectedJSON, actualJSON, new CustomComparator(JSONCompareMode.LENIENT, customization));
48 | }
49 |
50 | private void doFailingMatchTest(String jsonPath, ArrayValueMatcher arrayValueMatcher, String expectedJSON, String actualJSON, String expectedMessagePattern) {
51 | try {
52 | doTest(jsonPath, arrayValueMatcher, expectedJSON, actualJSON);
53 | }
54 | catch (AssertionError e) {
55 | String failureMessage = MessageFormat.format("Exception message ''{0}'', does not match expected pattern ''{1}''", e.getMessage(), expectedMessagePattern);
56 | assertTrue(failureMessage, e.getMessage().matches(expectedMessagePattern));
57 | return;
58 | }
59 | fail("AssertionError not thrown");
60 | }
61 |
62 | @Test
63 | public void matchesSecondElementOfJSONObjectArray() {
64 | doTest("a", new ArrayValueMatcher(comparator, 1), "{a:[{background:grey,id:2,type:row}]}", ARRAY_OF_JSONOBJECTS);
65 | }
66 |
67 | @Test
68 | public void failsWhenSecondElementOfJSONObjectArrayDoesNotMatch() {
69 | doFailingMatchTest("a",
70 | new ArrayValueMatcher(comparator, 1),
71 | "{a:[{background:DOES_NOT_MATCH,id:2,type:row}]}",
72 | ARRAY_OF_JSONOBJECTS,
73 | "a\\[1\\]\\.background\\s*Expected:\\s*DOES_NOT_MATCH\\s*got:\\s*grey\\s*");
74 | }
75 |
76 | @Test
77 | public void failsWhenThirdElementOfJSONObjectArrayDoesNotMatchInMultiplePlaces() {
78 | doFailingMatchTest("a",
79 | new ArrayValueMatcher(comparator, 2),
80 | "{a:[{background:DOES_NOT_MATCH,id:3,type:WRONG_TYPE}]}",
81 | ARRAY_OF_JSONOBJECTS,
82 | "a\\[2\\]\\.background\\s*Expected:\\s*DOES_NOT_MATCH\\s*got:\\s*white\\s*;\\s*a\\[2\\]\\.type\\s*Expected:\\s*WRONG_TYPE\\s*got:\\s*row\\s*");
83 | }
84 |
85 | @Test
86 | public void failsWhenTwoElementsOfJSONObjectArrayDoNotMatch() {
87 | doFailingMatchTest("a",
88 | new ArrayValueMatcher(comparator, 1, 2),
89 | "{a:[{background:DOES_NOT_MATCH,id:2,type:row},{background:white,id:3,type:WRONG_TYPE}]}",
90 | ARRAY_OF_JSONOBJECTS,
91 | "a\\[1\\]\\.background\\s*Expected:\\s*DOES_NOT_MATCH\\s*got:\\s*grey\\s*;\\s*a\\[2\\]\\.type\\s*Expected:\\s*WRONG_TYPE\\s*got:\\s*row\\s*");
92 | }
93 |
94 | @Test
95 | public void matchesThirdElementOfSimpleValueArray() {
96 | doTest("a", new ArrayValueMatcher(comparator, 2), "{a:[3]}", ARRAY_OF_INTEGERS);
97 | }
98 |
99 | @Test
100 | public void failsWhenTwoElementOfSimpleValueArrayDoNotMatch() {
101 | doFailingMatchTest("a", new ArrayValueMatcher(comparator, 3, 4), "{a:[3,4]}", ARRAY_OF_INTEGERS,
102 | "a\\[3\\]\\s*Expected:\\s3\\s*got:\\s*4\\s*;\\s*a\\[4\\]\\s*Expected:\\s*4\\s*got:\\s*5\\s*");
103 | }
104 |
105 | @Test
106 | public void matchesFirstElementOfArrayOfJSONArrays() {
107 | doTest("a", new ArrayValueMatcher(comparator, 0), "{a:[[6,7,8]]}", ARRAY_OF_JSONARRAYS);
108 | }
109 |
110 | @Test
111 | public void matchesSizeOfFirstThreeInnerArrays() {
112 | JSONComparator innerArraySizeComparator = new ArraySizeComparator(JSONCompareMode.STRICT_ORDER);
113 | doTest("a", new ArrayValueMatcher(innerArraySizeComparator, 0, 2), "{a:[[3]]}", ARRAY_OF_JSONARRAYS);
114 | }
115 |
116 | @Test
117 | public void failsWhenInnerArraySizeDoesNotMatch() {
118 | JSONComparator innerArraySizeComparator = new ArraySizeComparator(JSONCompareMode.STRICT_ORDER);
119 | doFailingMatchTest("a",
120 | new ArrayValueMatcher(innerArraySizeComparator),
121 | "{a:[[3]]}",
122 | ARRAY_OF_JSONARRAYS,
123 | "a\\[3\\]\\[\\]\\s*Expected:\\s*array size of 3 elements\\s*got:\\s*4 elements\\s*");
124 | }
125 |
126 | @Test
127 | public void failsWhenInnerJSONObjectArrayElementDoesNotMatch() {
128 | ArrayValueMatcher innerArrayValueMatcher = new ArrayValueMatcher(comparator, 1);
129 | JSONComparator innerArrayComparator = new CustomComparator(
130 | JSONCompareMode.LENIENT, new Customization("a[2]", innerArrayValueMatcher));
131 | doFailingMatchTest("a",
132 | new ArrayValueMatcher(innerArrayComparator, 2), // tests inner array i.e. [12,13,14]
133 | "{a:[[99]]}",
134 | ARRAY_OF_JSONARRAYS,
135 | "a\\[2\\]\\[1\\]\\s*Expected:\\s*99\\s*got:\\s*13\\s*");
136 | }
137 |
138 | @Test
139 | public void matchesEveryElementOfJSONObjectArray() {
140 | doTest("a", new ArrayValueMatcher(comparator), "{a:[{type:row}]}", ARRAY_OF_JSONOBJECTS);
141 | }
142 |
143 | @Test
144 | public void failsWhenNotEveryElementOfJSONObjectArrayMatches() {
145 | doFailingMatchTest("a",
146 | new ArrayValueMatcher(comparator),
147 | "{a:[{background:white}]}",
148 | ARRAY_OF_JSONOBJECTS,
149 | "a\\[1\\]\\.background\\s*Expected:\\s*white\\s*got:\\s*grey\\s*;\\s*a\\[3\\]\\.background\\s*Expected:\\s*white\\s*got:\\s*grey\\s*");
150 | }
151 |
152 | @Test
153 | public void matchesEveryElementOfJSONObjectArrayWhenRangeTooLarge() {
154 | doTest("a", new ArrayValueMatcher(comparator, 0, 500), "{a:[{type:row}]}", ARRAY_OF_JSONOBJECTS);
155 | }
156 |
157 | @Test
158 | public void matchesElementPairsStartingFromElement1OfJSONObjectArrayWhenRangeTooLarge() {
159 | doTest("a", new ArrayValueMatcher(comparator, 1, 500), "{a:[{background:grey},{background:white}]}", ARRAY_OF_JSONOBJECTS);
160 | }
161 |
162 | @Test
163 | public void matchesElementPairsStartingFromElement0OfJSONObjectArrayWhenRangeTooLarge() {
164 | doTest("a", new ArrayValueMatcher(comparator), "{a:[{background:white},{background:grey}]}", ARRAY_OF_JSONOBJECTS);
165 | }
166 |
167 | @Test
168 | public void failsWhenAppliedToNonArray() {
169 | try {
170 | doTest("a", new ArrayValueMatcher(comparator), "{a:[{background:white}]}", "{a:{attr1:value1,attr2:value2}}");
171 | }
172 | catch (IllegalArgumentException e) {
173 | assertEquals("Exception message", "ArrayValueMatcher applied to non-array actual value", e.getMessage());
174 | return;
175 | }
176 | fail("Did not throw IllegalArgumentException");
177 | }
178 |
179 | /*
180 | * Following tests verify the ability to match an element containing either
181 | * a simple value or a JSON object against simple value or JSON object
182 | * without requiring expected value to be wrapped in an array reducing
183 | * slightly the syntactic load on teh test author & reader.
184 | */
185 |
186 | @Test
187 | public void simpleValueMatchesSecondElementOfJSONObjectArray() {
188 | doTest("a", new ArrayValueMatcher(comparator, 3), "{a:4}", ARRAY_OF_INTEGERS);
189 | }
190 |
191 | @Test
192 | public void jsonObjectMatchesSecondElementOfJSONObjectArray() {
193 | doTest("a", new ArrayValueMatcher(comparator, 1), "{a:{background:grey,id:2,type:row}}", ARRAY_OF_JSONOBJECTS);
194 | }
195 |
196 | /*
197 | * Following tests contain copies of code quoted in ArrayValueMatcher JavaDoc and are included to verify that the exact code documented works as expected.
198 | */
199 | @Test
200 | public void verifyIdAttributeOfFirstArrayElementMatches() {
201 | JSONComparator comparator = new DefaultComparator(JSONCompareMode.LENIENT);
202 | Customization customization = new Customization("a", new ArrayValueMatcher(comparator, 0));
203 | JSONAssert.assertEquals("{a:[{id:1}]}", ARRAY_OF_JSONOBJECTS, new CustomComparator(JSONCompareMode.LENIENT, customization));
204 | }
205 |
206 | @Test
207 | public void verifyIdAttributeOfFirstArrayElementMatchesSimplifiedExpectedSyntax() {
208 | JSONComparator comparator = new DefaultComparator(JSONCompareMode.LENIENT);
209 | Customization customization = new Customization("a", new ArrayValueMatcher(comparator, 0));
210 | JSONAssert.assertEquals("{a:{id:1}}", ARRAY_OF_JSONOBJECTS, new CustomComparator(JSONCompareMode.LENIENT, customization));
211 | }
212 |
213 | @Test
214 | public void verifyTypeAttributeOfSecondAndThirdElementMatchesRow() {
215 | JSONComparator comparator = new DefaultComparator(JSONCompareMode.LENIENT);
216 | Customization customization = new Customization("a", new ArrayValueMatcher(comparator, 1, 2));
217 | JSONAssert.assertEquals("{a:[{type:row}]}", ARRAY_OF_JSONOBJECTS, new CustomComparator(JSONCompareMode.LENIENT, customization));
218 | }
219 |
220 | @Test
221 | public void verifyTypeAttributeOfEveryArrayElementMatchesRow() {
222 | JSONComparator comparator = new DefaultComparator(JSONCompareMode.LENIENT);
223 | Customization customization = new Customization("a", new ArrayValueMatcher(comparator));
224 | JSONAssert.assertEquals("{a:[{type:row}]}", ARRAY_OF_JSONOBJECTS, new CustomComparator(JSONCompareMode.LENIENT, customization));
225 | }
226 |
227 | @Test
228 | public void verifyEveryArrayElementWithCustomComparator() {
229 | // get length of array we will verify
230 | int aLength = ((JSONArray)((JSONObject)JSONParser.parseJSON(ARRAY_OF_JSONOBJECTS)).get("a")).length();
231 | // create array of customizations one for each array element
232 | RegularExpressionValueMatcher regExValueMatcher = new RegularExpressionValueMatcher("\\d+"); // matches one or more digits
233 | Customization[] customizations = new Customization[aLength];
234 | for (int i=0; i regExArrayValueMatcher = new ArrayValueMatcher(regExComparator);
241 | Customization regExArrayValueCustomization = new Customization("a", regExArrayValueMatcher);
242 | CustomComparator regExCustomArrayValueComparator = new CustomComparator(JSONCompareMode.STRICT_ORDER, new Customization[] { regExArrayValueCustomization });
243 | JSONAssert.assertEquals("{a:[{id:X}]}", ARRAY_OF_JSONOBJECTS, regExCustomArrayValueComparator);
244 | }
245 |
246 | @Test
247 | public void verifyBackgroundAttributesOfEveryArrayElementAlternateBetweenWhiteAndGrey() {
248 | JSONComparator comparator = new DefaultComparator(JSONCompareMode.LENIENT);
249 | Customization customization = new Customization("a", new ArrayValueMatcher(comparator));
250 | JSONAssert.assertEquals("{a:[{background:white},{background:grey}]}", ARRAY_OF_JSONOBJECTS, new CustomComparator(JSONCompareMode.LENIENT, customization));
251 | }
252 |
253 | @Test
254 | public void verifyEveryElementOfArrayIsJSONArrayOfLength3() {
255 | JSONComparator comparator = new ArraySizeComparator(JSONCompareMode.STRICT_ORDER);
256 | Customization customization = new Customization("a", new ArrayValueMatcher(comparator, 0, 2));
257 | JSONAssert.assertEquals("{a:[[3]]}", ARRAY_OF_JSONARRAYS, new CustomComparator(JSONCompareMode.LENIENT, customization));
258 | }
259 |
260 | @Test
261 | public void verifySecondElementOfArrayIsJSONArrayWhoseFirstElementIs9() {
262 | Customization innerCustomization = new Customization("a[1]", new ArrayValueMatcher(comparator, 0));
263 | JSONComparator comparator = new CustomComparator(JSONCompareMode.LENIENT, innerCustomization);
264 | Customization customization = new Customization("a", new ArrayValueMatcher(comparator, 1));
265 | JSONAssert.assertEquals("{a:[[9]]}", ARRAY_OF_JSONARRAYS, new CustomComparator(JSONCompareMode.LENIENT, customization));
266 | }
267 |
268 | @Test
269 | public void verifySecondElementOfArrayIsJSONArrayWhoseFirstElementIs9WithSimpliedExpectedString() {
270 | Customization innerCustomization = new Customization("a[1]", new ArrayValueMatcher(comparator, 0));
271 | JSONComparator comparator = new CustomComparator(JSONCompareMode.LENIENT, innerCustomization);
272 | Customization customization = new Customization("a", new ArrayValueMatcher(comparator, 1));
273 | JSONAssert.assertEquals("{a:[9]}", ARRAY_OF_JSONARRAYS, new CustomComparator(JSONCompareMode.LENIENT, customization));
274 | }
275 |
276 | @Test
277 | public void verifySecondElementOfArrayIsJSONArrayWhoseFirstElementIs9WithEvenMoreSimpliedExpectedString() {
278 | Customization innerCustomization = new Customization("a[1]", new ArrayValueMatcher(comparator, 0));
279 | JSONComparator comparator = new CustomComparator(JSONCompareMode.LENIENT, innerCustomization);
280 | Customization customization = new Customization("a", new ArrayValueMatcher(comparator, 1));
281 | JSONAssert.assertEquals("{a:9}", ARRAY_OF_JSONARRAYS, new CustomComparator(JSONCompareMode.LENIENT, customization));
282 | }
283 | }
284 |
--------------------------------------------------------------------------------
/src/test/java/org/skyscreamer/jsonassert/DependencyTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert;
16 |
17 | import org.json.JSONObject;
18 | import org.junit.Assert;
19 | import org.junit.Test;
20 |
21 | /**
22 | * Unit tests for our external/third-party dependencies.
23 | *
24 | * @author Carter Page
25 | */
26 | public class DependencyTest {
27 | @Test
28 | public void nop() {
29 | // Cloudbees doesn't like a unit test class with no tests
30 | }
31 |
32 | //@Test // For https://github.com/skyscreamer/JSONassert/issues/25
33 | public void testJSonGetLong() throws Exception {
34 | Long target = -4611686018427386614L;
35 | String targetString = target.toString();
36 |
37 | JSONObject value = new JSONObject().put("id", target);
38 | Assert.assertEquals(target, (Long) value.getLong("id")); //Correct: when put as long getLong is correct
39 |
40 | value = new JSONObject().put("id", targetString);
41 | Assert.assertEquals(target, (Long) Long.parseLong(value.getString("id"))); //Correct: when put as String getString is correct
42 | Assert.assertEquals(target, (Long) value.getLong("id")); //Bug: Having json convert the string to long fails
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/test/java/org/skyscreamer/jsonassert/JSONArrayWithNullTest.java:
--------------------------------------------------------------------------------
1 | package org.skyscreamer.jsonassert;
2 |
3 | import org.json.JSONArray;
4 | import org.json.JSONObject;
5 | import org.junit.Test;
6 |
7 | public class JSONArrayWithNullTest {
8 | @Test
9 | public void testJSONArrayWithNullValue() {
10 | JSONArray jsonArray1 = getJSONArray1();
11 | JSONArray jsonArray2 = getJSONArray2();
12 |
13 | JSONAssert.assertEquals(jsonArray1, jsonArray2, true);
14 | JSONAssert.assertEquals(jsonArray1, jsonArray2, false);
15 | }
16 |
17 | @Test
18 | public void testJSONArrayWithNullValueAndJsonObject() {
19 | JSONArray jsonArray1 = getJSONArray1();
20 | JSONObject jsonObject1 = new JSONObject();
21 | jsonObject1.put("hey", "value");
22 |
23 | JSONArray jsonArray2 = getJSONArray2();
24 | JSONObject jsonObject2 = new JSONObject();
25 | jsonObject2.put("hey", "value");
26 |
27 | JSONAssert.assertEquals(jsonArray1, jsonArray2, true);
28 | JSONAssert.assertEquals(jsonArray1, jsonArray2, false);
29 | }
30 |
31 | private JSONArray getJSONArray1() {
32 | JSONArray jsonArray1 = new JSONArray();
33 | jsonArray1.put(1);
34 | jsonArray1.put(JSONObject.NULL);
35 | jsonArray1.put(3);
36 | jsonArray1.put(2);
37 | return jsonArray1;
38 | }
39 |
40 | private JSONArray getJSONArray2() {
41 | JSONArray jsonArray1 = new JSONArray();
42 | jsonArray1.put(1);
43 | jsonArray1.put(JSONObject.NULL);
44 | jsonArray1.put(3);
45 | jsonArray1.put(2);
46 | return jsonArray1;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/test/java/org/skyscreamer/jsonassert/JSONCompareModeTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert;
16 |
17 | import static junit.framework.Assert.assertEquals;
18 | import static junit.framework.Assert.assertFalse;
19 | import static junit.framework.Assert.assertTrue;
20 | import static org.skyscreamer.jsonassert.JSONCompareMode.LENIENT;
21 | import static org.skyscreamer.jsonassert.JSONCompareMode.NON_EXTENSIBLE;
22 | import static org.skyscreamer.jsonassert.JSONCompareMode.STRICT;
23 | import static org.skyscreamer.jsonassert.JSONCompareMode.STRICT_ORDER;
24 |
25 | import org.junit.Test;
26 |
27 | /**
28 | * Unit tests for {@link JSONCompareMode}
29 | */
30 | public class JSONCompareModeTest {
31 | @Test
32 | public void testWithStrictOrdering() {
33 | assertTrue(LENIENT.withStrictOrdering(true).hasStrictOrder());
34 | assertTrue(LENIENT.withStrictOrdering(true).isExtensible());
35 | assertTrue(NON_EXTENSIBLE.withStrictOrdering(true).hasStrictOrder());
36 | assertFalse(NON_EXTENSIBLE.withStrictOrdering(true).isExtensible());
37 |
38 | assertEquals(STRICT, STRICT.withStrictOrdering(true));
39 | assertEquals(STRICT_ORDER, STRICT_ORDER.withStrictOrdering(true));
40 | }
41 |
42 | @Test
43 | public void testWithoutStrictOrdering() {
44 | assertFalse(STRICT_ORDER.withStrictOrdering(false).hasStrictOrder());
45 | assertTrue(STRICT_ORDER.withStrictOrdering(false).isExtensible());
46 | assertFalse(STRICT.withStrictOrdering(false).hasStrictOrder());
47 | assertFalse(STRICT.withStrictOrdering(false).isExtensible());
48 |
49 | assertEquals(LENIENT, LENIENT.withStrictOrdering(false));
50 | assertEquals(NON_EXTENSIBLE, NON_EXTENSIBLE.withStrictOrdering(false));
51 | }
52 |
53 | @Test
54 | public void testWithExtensibility() {
55 | assertTrue(NON_EXTENSIBLE.withExtensible(true).isExtensible());
56 | assertFalse(NON_EXTENSIBLE.withExtensible(true).hasStrictOrder());
57 | assertTrue(STRICT.withExtensible(true).isExtensible());
58 | assertTrue(STRICT.withExtensible(true).hasStrictOrder());
59 |
60 | assertEquals(LENIENT, LENIENT.withExtensible(true));
61 | assertEquals(STRICT_ORDER, STRICT_ORDER.withExtensible(true));
62 | }
63 |
64 | @Test
65 | public void testWithoutExtensibility() {
66 | assertFalse(STRICT_ORDER.withExtensible(false).isExtensible());
67 | assertTrue(STRICT_ORDER.withExtensible(false).hasStrictOrder());
68 | assertFalse(LENIENT.withExtensible(false).isExtensible());
69 | assertFalse(LENIENT.withExtensible(false).hasStrictOrder());
70 |
71 | assertEquals(STRICT, STRICT.withExtensible(false));
72 | assertEquals(NON_EXTENSIBLE, NON_EXTENSIBLE.withExtensible(false));
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/test/java/org/skyscreamer/jsonassert/JSONCompareTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert;
16 |
17 | import static org.hamcrest.core.IsEqual.equalTo;
18 | import static org.junit.Assert.assertEquals;
19 | import static org.junit.Assert.assertThat;
20 | import static org.junit.Assert.assertTrue;
21 | import static org.skyscreamer.jsonassert.JSONCompare.compareJSON;
22 | import static org.skyscreamer.jsonassert.JSONCompareMode.LENIENT;
23 | import static org.skyscreamer.jsonassert.JSONCompareMode.NON_EXTENSIBLE;
24 | import static org.skyscreamer.jsonassert.JSONCompareMode.STRICT;
25 |
26 | import org.hamcrest.Description;
27 | import org.hamcrest.Matcher;
28 | import org.junit.Test;
29 | import org.junit.internal.matchers.TypeSafeMatcher;
30 |
31 | /**
32 | * Unit tests for {@code JSONCompare}.
33 | */
34 | public class JSONCompareTest {
35 | @Test
36 | public void succeedsWithEmptyArrays() {
37 | assertTrue(compareJSON("[]", "[]", LENIENT).passed());
38 | }
39 |
40 | @Test
41 | public void reportsArraysOfUnequalLength() {
42 | JSONCompareResult result = compareJSON("[4]", "[]", LENIENT);
43 | assertThat(result, failsWithMessage(equalTo("[]: Expected 1 values but got 0")));
44 | }
45 |
46 | @Test
47 | public void reportsArrayMissingExpectedElement() {
48 | JSONCompareResult result = compareJSON("[4]", "[7]", LENIENT);
49 | assertThat(result, failsWithMessage(equalTo("[]\nExpected: 4\n but none found\n ; []\nUnexpected: 7\n")));
50 | assertEquals(result.getFieldMissing().size(), 1);
51 | assertEquals(result.getFieldUnexpected().size(), 1);
52 | }
53 |
54 | @Test
55 | public void reportsMismatchedFieldValues() {
56 | JSONCompareResult result = compareJSON("{\"id\": 3}", "{\"id\": 5}", LENIENT);
57 | assertThat(result, failsWithMessage(equalTo("id\nExpected: 3\n got: 5\n")));
58 | assertThat(result, failsWithMessage(equalTo("id\nExpected: 3\n got: 5\n")));
59 | }
60 |
61 | @Test
62 | public void reportsMissingField() {
63 | JSONCompareResult result = compareJSON("{\"obj\": {\"id\": 3}}", "{\"obj\": {}}", LENIENT);
64 | assertThat(result, failsWithMessage(equalTo("obj\nExpected: id\n but none found\n")));
65 | assertEquals(result.getFieldMissing().size(), 1);
66 | }
67 |
68 | @Test
69 | public void reportsUnexpectedArrayWhenExpectingObject() {
70 | JSONCompareResult result = compareJSON("{}", "[]", LENIENT);
71 | assertThat(result, failsWithMessage(equalTo("\nExpected: a JSON object\n got: a JSON array\n")));
72 | }
73 |
74 | @Test
75 | public void reportsUnexpectedObjectWhenExpectingArray() {
76 | JSONCompareResult result = compareJSON("[]", "{}", LENIENT);
77 | assertThat(result, failsWithMessage(equalTo("\nExpected: a JSON array\n got: a JSON object\n")));
78 | }
79 |
80 | @Test
81 | public void reportsUnexpectedNull() {
82 | JSONCompareResult result = compareJSON("{\"id\": 3}", "{\"id\": null}", LENIENT);
83 | assertThat(result, failsWithMessage(equalTo("id\nExpected: 3\n got: null\n")));
84 | }
85 |
86 | @Test
87 | public void reportsUnexpectedNonNull() {
88 | JSONCompareResult result = compareJSON("{\"id\": null}", "{\"id\": \"abc\"}", LENIENT);
89 | assertThat(result, failsWithMessage(equalTo("id\nExpected: null\n got: abc\n")));
90 | }
91 |
92 | @Test
93 | public void reportsUnexpectedFieldInNonExtensibleMode() {
94 | JSONCompareResult result = compareJSON("{\"obj\": {}}", "{\"obj\": {\"id\": 3}}", NON_EXTENSIBLE);
95 | assertThat(result, failsWithMessage(equalTo("obj\nUnexpected: id\n")));
96 | assertEquals(result.getFieldUnexpected().size(), 1);
97 | }
98 |
99 | @Test
100 | public void reportsMismatchedTypes() {
101 | JSONCompareResult result = compareJSON("{\"arr\":[]}", "{\"arr\":{}}", LENIENT);
102 | assertThat(result, failsWithMessage(equalTo("arr\nExpected: a JSON array\n got: a JSON object\n")));
103 | }
104 |
105 | @Test
106 | public void reportsWrongSimpleValueCountInUnorderedArray() {
107 | JSONCompareResult result = compareJSON("[5, 5]", "[5, 7]", LENIENT);
108 | assertThat(result, failsWithMessage(equalTo("[]: Expected 2 occurrence(s) of 5 but got 1 occurrence(s) ; []\nUnexpected: 7\n")));
109 | assertEquals(result.getFieldUnexpected().size(), 1);
110 | }
111 |
112 | @Test
113 | public void reportsMissingJSONObjectWithUniqueKeyInUnorderedArray() {
114 | JSONCompareResult result = compareJSON("[{\"id\" : 3}]", "[{\"id\" : 5}]", LENIENT);
115 | assertThat(result, failsWithMessage(equalTo("[id=3]\nExpected: a JSON object\n but none found\n ; " +
116 | "[id=5]\nUnexpected: a JSON object\n")));
117 | assertEquals(result.getFieldMissing().size(), 1);
118 | assertEquals(result.getFieldUnexpected().size(), 1);
119 | }
120 |
121 | @Test
122 | public void reportsUnmatchedJSONObjectInUnorderedArray() {
123 | JSONCompareResult result = compareJSON("[{\"address\" : {\"street\" : \"Acacia Avenue\"}}]", "[{\"age\" : 23}]", LENIENT);
124 | assertThat(result, failsWithMessage(equalTo("[0] Could not find match for element {\"address\":{\"street\":\"Acacia Avenue\"}}")));
125 | }
126 |
127 | @Test
128 | public void succeedsWithNestedJSONObjectsInUnorderedArray() {
129 | assertTrue(compareJSON("[{\"address\" : {\"street\" : \"Acacia Avenue\"}}, 5]", "[5, {\"address\" : {\"street\" : \"Acacia Avenue\"}}]", LENIENT).passed());
130 | }
131 |
132 | @Test
133 | public void succeedsWithJSONObjectsWithNonUniqueKeyInUnorderedArray() {
134 | String jsonDocument = "[{\"age\" : 43}, {\"age\" : 43}]";
135 | assertTrue(compareJSON(jsonDocument, jsonDocument, LENIENT).passed());
136 | }
137 |
138 | @Test
139 | public void succeedsWithSomeNestedJSONObjectsInUnorderedArray() {
140 | String jsonDocument = "[{\"age\" : 43}, {\"age\" : {\"years\" : 43}}]";
141 | assertTrue(compareJSON(jsonDocument, jsonDocument, LENIENT).passed());
142 | }
143 |
144 | @Test
145 | public void reportsUnmatchesIntegerValueInUnorderedArrayContainingJSONObject() {
146 | JSONCompareResult result = compareJSON("[{\"address\" : {\"street\" : \"Acacia Avenue\"}}, 5]", "[{\"address\" : {\"street\" : \"Acacia Avenue\"}}, 2]", LENIENT);
147 | assertThat(result, failsWithMessage(equalTo("[1] Could not find match for element 5")));
148 | }
149 |
150 | @Test
151 | public void reportsUnmatchedJSONArrayWhereOnlyExpectedContainsJSONObjectWithUniqueKey() {
152 | JSONCompareResult result = compareJSON("[{\"id\": 3}]", "[{}]", LENIENT);
153 | assertThat(result, failsWithMessage(equalTo("[0] Could not find match for element {\"id\":3}")));
154 | }
155 |
156 | @Test
157 | public void reportsUnmatchedJSONArrayWhereExpectedContainsJSONObjectWithUniqueKeyButActualContainsElementOfOtherType() {
158 | JSONCompareResult result = compareJSON("[{\"id\": 3}]", "[5]", LENIENT);
159 | assertThat(result, failsWithMessage(equalTo("[0] Could not find match for element {\"id\":3}")));
160 | }
161 |
162 | @Test
163 | public void reportsUnmatchedJSONArrayWhereExpectedContainsNonnullIntegerButActualContainsNullElement() {
164 | JSONCompareResult result = compareJSON("[ 3 ]", "[ null ]", LENIENT);
165 | assertThat(result, failsWithMessage(equalTo("[]\nExpected: 3\n but none found\n ; " +
166 | "[]\nUnexpected: null\n")));
167 | }
168 |
169 | @Test
170 | public void reportsUnmatchedJSONArrayWhereExpectedContainsNullElementButActualContainsNonnullInteger() {
171 | JSONCompareResult result = compareJSON("[ null ]", "[ 3 ]", LENIENT);
172 | assertThat(result, failsWithMessage(equalTo("[]\nExpected: null\n but none found\n ; " +
173 | "[]\nUnexpected: 3\n")));
174 | }
175 |
176 | @Test
177 | public void reportsStrictUnmatchedJSONArrayWhereExpectedContainsNonnullIntegerButActualContainsNullElement() {
178 | JSONCompareResult result = compareJSON("[ 3 ]", "[ null ]", STRICT);
179 | assertThat(result, failsWithMessage(equalTo("[0]\nExpected: 3\n got: null\n")));
180 | }
181 |
182 | @Test
183 | public void reportsStrictUnmatchedJSONArrayWhereExpectedContainsNullButActualContainsNonnullInteger() {
184 | JSONCompareResult result = compareJSON("[ null ]", "[ 3 ]", STRICT);
185 | assertThat(result, failsWithMessage(equalTo("[0]\nExpected: null\n got: 3\n")));
186 | }
187 |
188 | private Matcher failsWithMessage(final Matcher expectedMessage) {
189 | return new TypeSafeMatcher() {
190 | @Override
191 | public void describeTo(Description description) {
192 | description.appendText("a failed comparison with message ").appendDescriptionOf(expectedMessage);
193 | }
194 |
195 | @Override
196 | public boolean matchesSafely(JSONCompareResult item) {
197 | return item.failed() && expectedMessage.matches(item.getMessage());
198 | }
199 | };
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/src/test/java/org/skyscreamer/jsonassert/JSONCustomComparatorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert;
16 |
17 | import org.junit.Test;
18 | import org.skyscreamer.jsonassert.comparator.CustomComparator;
19 | import org.skyscreamer.jsonassert.comparator.JSONComparator;
20 |
21 | import static org.junit.Assert.assertEquals;
22 | import static org.junit.Assert.assertTrue;
23 | import static org.skyscreamer.jsonassert.JSONCompare.compareJSON;
24 |
25 | public class JSONCustomComparatorTest {
26 |
27 | String actual = "{\"first\":\"actual\", \"second\":1}";
28 | String expected = "{\"first\":\"expected\", \"second\":1}";
29 |
30 | String deepActual = "{\n" +
31 | " \"outer\":\n" +
32 | " {\n" +
33 | " \"inner\":\n" +
34 | " {\n" +
35 | " \"value\": \"actual\",\n" +
36 | " \"otherValue\": \"foo\"\n" +
37 | " }\n" +
38 | " }\n" +
39 | "}";
40 | String deepExpected = "{\n" +
41 | " \"outer\":\n" +
42 | " {\n" +
43 | " \"inner\":\n" +
44 | " {\n" +
45 | " \"value\": \"expected\",\n" +
46 | " \"otherValue\": \"foo\"\n" +
47 | " }\n" +
48 | " }\n" +
49 | "}";
50 |
51 | String simpleWildcardActual = "{\n" +
52 | " \"foo\": {\n" +
53 | " \"bar1\": {\n" +
54 | " \"baz\": \"actual\"\n" +
55 | " },\n" +
56 | " \"bar2\": {\n" +
57 | " \"baz\": \"actual\"\n" +
58 | " }\n" +
59 | " }\n" +
60 | "}";
61 | String simpleWildcardExpected = "{\n" +
62 | " \"foo\": {\n" +
63 | " \"bar1\": {\n" +
64 | " \"baz\": \"expected\"\n" +
65 | " },\n" +
66 | " \"bar2\": {\n" +
67 | " \"baz\": \"expected\"\n" +
68 | " }\n" +
69 | " }\n" +
70 | "}";
71 |
72 | String deepWildcardActual = "{\n" +
73 | " \"root\": {\n" +
74 | " \"baz\": \"actual\",\n" +
75 | " \"foo\": {\n" +
76 | " \"baz\": \"actual\",\n" +
77 | " \"bar\": {\n" +
78 | " \"baz\": \"actual\"\n" +
79 | " }\n" +
80 | " }\n" +
81 | " }\n" +
82 | "}";
83 | String deepWildcardExpected = "{\n" +
84 | " \"root\": {\n" +
85 | " \"baz\": \"expected\",\n" +
86 | " \"foo\": {\n" +
87 | " \"baz\": \"expected\",\n" +
88 | " \"bar\": {\n" +
89 | " \"baz\": \"expected\"\n" +
90 | " }\n" +
91 | " }\n" +
92 | " }\n" +
93 | "}";
94 |
95 | String rootDeepWildcardActual = "{\n" +
96 | " \"baz\": \"actual\",\n" +
97 | " \"root\": {\n" +
98 | " \"baz\": \"actual\",\n" +
99 | " \"foo\": {\n" +
100 | " \"baz\": \"actual\",\n" +
101 | " \"bar\": {\n" +
102 | " \"baz\": \"actual\"\n" +
103 | " }\n" +
104 | " }\n" +
105 | " }\n" +
106 | "}";
107 | String rootDeepWildcardExpected = "{\n" +
108 | " \"baz\": \"expected\",\n" +
109 | " \"root\": {\n" +
110 | " \"baz\": \"expected\",\n" +
111 | " \"foo\": {\n" +
112 | " \"baz\": \"expected\",\n" +
113 | " \"bar\": {\n" +
114 | " \"baz\": \"expected\"\n" +
115 | " }\n" +
116 | " }\n" +
117 | " }\n" +
118 | "}";
119 |
120 | int comparatorCallCount = 0;
121 | ValueMatcher comparator = new ValueMatcher() {
122 | @Override
123 | public boolean equal(Object o1, Object o2) {
124 | comparatorCallCount++;
125 | return o1.toString().equals("actual") && o2.toString().equals("expected");
126 | }
127 | };
128 |
129 | @Test
130 | public void whenPathMatchesInCustomizationThenCallCustomMatcher() {
131 | JSONComparator jsonCmp = new CustomComparator(JSONCompareMode.STRICT, new Customization("first", comparator));
132 | JSONCompareResult result = compareJSON(expected, actual, jsonCmp);
133 | assertTrue(result.getMessage(), result.passed());
134 | assertEquals(1, comparatorCallCount);
135 | }
136 |
137 | @Test
138 | public void whenDeepPathMatchesCallCustomMatcher() {
139 | JSONComparator jsonCmp = new CustomComparator(JSONCompareMode.STRICT, new Customization("outer.inner.value", comparator));
140 | JSONCompareResult result = compareJSON(deepExpected, deepActual, jsonCmp);
141 | assertTrue(result.getMessage(), result.passed());
142 | assertEquals(1, comparatorCallCount);
143 | }
144 |
145 | @Test
146 | public void whenSimpleWildcardPathMatchesCallCustomMatcher() {
147 | JSONComparator jsonCmp = new CustomComparator(JSONCompareMode.STRICT, new Customization("foo.*.baz", comparator));
148 | JSONCompareResult result = compareJSON(simpleWildcardExpected, simpleWildcardActual, jsonCmp);
149 | assertTrue(result.getMessage(), result.passed());
150 | assertEquals(2, comparatorCallCount);
151 | }
152 |
153 | @Test
154 | public void whenDeepWildcardPathMatchesCallCustomMatcher() {
155 | JSONComparator jsonCmp = new CustomComparator(JSONCompareMode.STRICT, new Customization("root.**.baz", comparator));
156 | JSONCompareResult result = compareJSON(deepWildcardExpected, deepWildcardActual, jsonCmp);
157 | assertTrue(result.getMessage(), result.passed());
158 | assertEquals(3, comparatorCallCount);
159 | }
160 |
161 | @Test
162 | public void whenRootDeepWildcardPathMatchesCallCustomMatcher() {
163 | JSONComparator jsonCmp = new CustomComparator(JSONCompareMode.STRICT, new Customization("**.baz", comparator));
164 | JSONCompareResult result = compareJSON(rootDeepWildcardExpected, rootDeepWildcardActual, jsonCmp);
165 | assertTrue(result.getMessage(), result.passed());
166 | assertEquals(4, comparatorCallCount);
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/src/test/java/org/skyscreamer/jsonassert/RegularExpressionValueMatcherTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert;
16 |
17 | import org.junit.Assert;
18 |
19 | import org.junit.Test;
20 | import org.skyscreamer.jsonassert.comparator.CustomComparator;
21 |
22 | /**
23 | * Unit tests for RegularExpressionValueMatcher
24 | *
25 | * @author Duncan Mackinder
26 | *
27 | */
28 | public class RegularExpressionValueMatcherTest {
29 | private static final String ARRAY_ELEMENT_PREFIX = "d.results[0].__metadata.uri";
30 | private static final String JSON_STRING_WITH_ARRAY = "{d:{results:[{__metadata:{uri:\"http://localhost:80/Person('1')\",type:Person},id:1}]}}";
31 | private static final String CONSTANT_URI_REGEX_EXPECTED_JSON = "{d:{results:[{__metadata:{uri:X}}]}}";
32 |
33 | private void doTest(String jsonPath, String regex, String expectedJSON,
34 | String actualJSON) {
35 | JSONAssert.assertEquals(expectedJSON, actualJSON, new CustomComparator(
36 | JSONCompareMode.STRICT_ORDER, new Customization(jsonPath,
37 | new RegularExpressionValueMatcher(regex))));
38 | }
39 |
40 | @Test
41 | public void constantRegexWithSimplePathMatchsStringAttribute() {
42 | doTest("a", "v.", "{a:x}", "{a:v1}");
43 | }
44 |
45 | @Test
46 | public void constantRegexWithThreeLevelPathMatchsStringAttribute() {
47 | doTest("a.b.c", ".*Is.*", "{a:{b:{c:x}}}", "{a:{b:{c:thisIsAString}}}");
48 | }
49 |
50 | @Test
51 | public void dynamicRegexWithSimplePathMatchsStringAttribute() {
52 | doTest("a", null, "{a:\"v.\"}", "{a:v1}");
53 | }
54 |
55 | @Test
56 | public void dynamicRegexWithThreeLevelPathMatchsStringAttribute() {
57 | doTest("a.b.c", null, "{a:{b:{c:\".*Is.*\"}}}",
58 | "{a:{b:{c:thisIsAString}}}");
59 | }
60 |
61 | @Test
62 | public void constantRegexMatchesStringAttributeInsideArray() {
63 | doTest(ARRAY_ELEMENT_PREFIX, "http://localhost:80/Person\\('\\d+'\\)", CONSTANT_URI_REGEX_EXPECTED_JSON, JSON_STRING_WITH_ARRAY);
64 | }
65 |
66 | @Test
67 | public void dynamicRegexMatchesStringAttributeInsideArray() {
68 | doTest(ARRAY_ELEMENT_PREFIX, null, "{d:{results:[{__metadata:{uri:\"http://localhost:80/Person\\\\('\\\\d+'\\\\)\"}}]}}", JSON_STRING_WITH_ARRAY);
69 | }
70 |
71 | @Test
72 | public void dynamicRegexMatchesStringAttributeInsideArrayWithNoArgConstructor() {
73 | JSONAssert.assertEquals("{d:{results:[{__metadata:{uri:\"http://localhost:80/Person\\\\('\\\\d+'\\\\)\"}}]}}", JSON_STRING_WITH_ARRAY, new CustomComparator(
74 | JSONCompareMode.STRICT_ORDER, new Customization(ARRAY_ELEMENT_PREFIX,
75 | new RegularExpressionValueMatcher())));
76 | }
77 |
78 | @Test
79 | public void failsWhenDynamicRegexInvalid() {
80 | try {
81 | doTest(ARRAY_ELEMENT_PREFIX, null, "{d:{results:[{__metadata:{uri:\"http://localhost:80/Person('\\\\d+'\\\\)\"}}]}}", JSON_STRING_WITH_ARRAY);
82 | }
83 | catch (AssertionError e) {
84 | Assert.assertTrue("Invalid exception message returned: "+ e.getMessage(), e.getMessage().startsWith(ARRAY_ELEMENT_PREFIX + ": Dynamic expected pattern invalid: "));
85 | }
86 | }
87 |
88 | @Test
89 | public void failsWhenDynamicRegexDoesNotMatchStringAttributeInsideArray() {
90 | try {
91 | doTest(ARRAY_ELEMENT_PREFIX, null, "{d:{results:[{__metadata:{uri:\"http://localhost:80/Person\\\\('\\\\w+'\\\\)\"}}]}}", JSON_STRING_WITH_ARRAY);
92 | }
93 | catch (AssertionError e) {
94 | Assert.assertTrue("Invalid exception message returned: "+ e.getMessage(), e.getMessage().startsWith(ARRAY_ELEMENT_PREFIX + ": Dynamic expected pattern did not match value"));
95 | }
96 | }
97 |
98 | @Test
99 | public void failsWhenConstantRegexInvalid() {
100 | try {
101 | doTest(ARRAY_ELEMENT_PREFIX, "http://localhost:80/Person\\\\['\\\\d+'\\\\)", CONSTANT_URI_REGEX_EXPECTED_JSON, JSON_STRING_WITH_ARRAY);
102 | }
103 | catch (IllegalArgumentException e) {
104 | Assert.assertTrue("Invalid exception message returned: "+ e.getMessage(), e.getMessage().startsWith("Constant expected pattern invalid: "));
105 | }
106 | }
107 |
108 | @Test
109 | public void failsWhenConstantRegexDoesNotMatchStringAttributeInsideArray() {
110 | try {
111 | doTest(ARRAY_ELEMENT_PREFIX, "http://localhost:80/Person\\\\('\\\\w+'\\\\)", CONSTANT_URI_REGEX_EXPECTED_JSON, JSON_STRING_WITH_ARRAY);
112 | }
113 | catch (AssertionError e) {
114 | Assert.assertTrue("Invalid exception message returned: "+ e.getMessage(), e.getMessage().startsWith(ARRAY_ELEMENT_PREFIX + ": Constant expected pattern did not match value"));
115 | }
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/test/java/org/skyscreamer/jsonassert/comparator/ArraySizeComparatorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert.comparator;
16 |
17 | import static org.junit.Assert.assertTrue;
18 | import static org.junit.Assert.fail;
19 |
20 | import java.text.MessageFormat;
21 |
22 | import org.junit.Test;
23 | import org.skyscreamer.jsonassert.JSONAssert;
24 | import org.skyscreamer.jsonassert.JSONCompareMode;
25 |
26 | /**
27 | * Unit tests for ArraySizeComparator
28 | *
29 | * @author Duncan Mackinder
30 | *
31 | */
32 | public class ArraySizeComparatorTest {
33 | private static final String twoElementArray = "{a:[b,c]}";
34 |
35 | private void doTest(String expectedJSON, String actualJSON)
36 | {
37 | JSONAssert.assertEquals(expectedJSON, actualJSON, new ArraySizeComparator(JSONCompareMode.STRICT_ORDER));
38 | }
39 |
40 | private void doFailingMatchTest(String expectedJSON, String actualJSON, String expectedMessagePattern) {
41 | try {
42 | doTest(expectedJSON, actualJSON);
43 | }
44 | catch (AssertionError e) {
45 | String failureMessage = MessageFormat.format("Exception message ''{0}'', does not match expected pattern ''{1}''", e.getMessage(), expectedMessagePattern);
46 | assertTrue(failureMessage, e.getMessage().matches(expectedMessagePattern));
47 | return;
48 | }
49 | fail("AssertionError not thrown");
50 | }
51 |
52 | @Test
53 | public void succeedsWhenExactSizeExpected() {
54 | doTest("{a:[2]}", twoElementArray);
55 | }
56 |
57 | @Test
58 | public void succeedsWhenSizeWithinExpectedRange() {
59 | doTest("{a:[1,3]}", twoElementArray);
60 | }
61 |
62 | @Test
63 | public void succeedsWhenSizeIsMinimumOfExpectedRange() {
64 | doTest("{a:[2,4]}", twoElementArray);
65 | }
66 |
67 | @Test
68 | public void succeedsWhenSizeIsMaximumOfExpectedRange() {
69 | doTest("{a:[1,2]}", twoElementArray);
70 | }
71 |
72 | @Test
73 | public void failsWhenExpectedArrayTooShort() {
74 | doFailingMatchTest("{a:[]}", twoElementArray, "a\\[\\]: invalid expectation: expected array should contain either 1 or 2 elements but contains 0 elements");
75 | }
76 |
77 | @Test
78 | public void failsWhenExpectedArrayTooLong() {
79 | doFailingMatchTest("{a:[1,2,3]}", twoElementArray, "a\\[\\]: invalid expectation: expected array should contain either 1 or 2 elements but contains 3 elements");
80 | }
81 |
82 | @Test
83 | public void failsWhenExpectedNotAllSimpleTypes() {
84 | doFailingMatchTest("{a:[{y:1},2]}", twoElementArray, "a\\[\\]: invalid expectation: minimum expected array size '\\{\"y\":1\\}' not a number");
85 | }
86 |
87 | @Test
88 | public void failsWhenExpectedMinimumTooSmall() {
89 | doFailingMatchTest("{a:[-1,6]}", twoElementArray, "a\\[\\]: invalid expectation: minimum expected array size '-1' negative");
90 | }
91 |
92 | @Test
93 | public void failsWhenExpectedMaximumTooSmall() {
94 | doFailingMatchTest("{a:[8,6]}", twoElementArray, "a\\[\\]: invalid expectation: maximum expected array size '6' less than minimum expected array size '8'");
95 | }
96 |
97 | @Test
98 | public void failsWhenExpectedArraySizeNotANumber() {
99 | doFailingMatchTest("{a:[X]}", twoElementArray, "a\\[\\]: invalid expectation: expected array size 'X' not a number");
100 | }
101 |
102 | @Test
103 | public void failsWhenFirstExpectedArrayElementNotANumber() {
104 | doFailingMatchTest("{a:[MIN,6]}", twoElementArray, "a\\[\\]: invalid expectation: minimum expected array size 'MIN' not a number");
105 | }
106 |
107 | @Test
108 | public void failsWhenSecondExpectedArrayElementNotANumber() {
109 | doFailingMatchTest("{a:[8,MAX]}", twoElementArray, "a\\[\\]: invalid expectation: maximum expected array size 'MAX' not a number");
110 | }
111 |
112 | @Test
113 | public void failsWhenActualArrayTooShort() {
114 | doFailingMatchTest("{a:[3]}", twoElementArray, "a\\[\\]\\s*Expected:\\s*array size of 3 elements\\s*got:\\s*2 elements\\s*");
115 | }
116 |
117 | @Test
118 | public void failsWhenActualArrayLongerThanExpectedLength() {
119 | doFailingMatchTest("{a:[1]}", twoElementArray, "a\\[\\]\\s*Expected:\\s*array size of 1 elements\\s*got:\\s*2 elements\\s*");
120 | }
121 |
122 | @Test
123 | public void failsWhenActualArrayLongerThanMaxOfExpectedRange() {
124 | doFailingMatchTest("{a:[0,1]}", twoElementArray, "a\\[\\]\\s*Expected:\\s*array size of 0 to 1 elements\\s*got:\\s*2 elements\\s*");
125 | }
126 |
127 | /*
128 | * Following tests are copied from ArraySizeComparator JavaDoc and are include to ensure code as documented work as expected.
129 | */
130 |
131 | @Test
132 | public void succeedsWhenActualArrayContainsExactly3Elements() {
133 | JSONAssert.assertEquals("{a:[3]}", "{a:[7, 8, 9]}", new ArraySizeComparator(JSONCompareMode.LENIENT));
134 | }
135 |
136 | @Test
137 | public void succeedsWhenActualArrayContainsBetween2And6Elements() {
138 | JSONAssert.assertEquals("{a:[2,6]}", "{a:[7, 8, 9]}", new ArraySizeComparator(JSONCompareMode.LENIENT));
139 | }
140 |
141 | }
142 |
--------------------------------------------------------------------------------
/src/test/java/org/skyscreamer/jsonassert/comparator/CustomComparatorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert.comparator;
16 |
17 | import junit.framework.Assert;
18 | import org.json.JSONArray;
19 | import org.junit.Test;
20 | import org.skyscreamer.jsonassert.JSONCompare;
21 | import org.skyscreamer.jsonassert.JSONCompareMode;
22 | import org.skyscreamer.jsonassert.JSONCompareResult;
23 |
24 | /**
25 | * @author Ivan Zaytsev
26 | * 2013-01-04
27 | */
28 | public class CustomComparatorTest {
29 |
30 | private static class ArrayOfJsonObjectsComparator extends DefaultComparator {
31 | public ArrayOfJsonObjectsComparator(JSONCompareMode mode) {
32 | super(mode);
33 | }
34 |
35 | @Override
36 | public void compareJSONArray(String prefix, JSONArray expected, JSONArray actual, JSONCompareResult result) {
37 | compareJSONArrayOfJsonObjects(prefix, expected, actual, result);
38 | }
39 | }
40 |
41 | @Test
42 | public void testFullArrayComparison() throws Exception {
43 | JSONCompareResult compareResult = JSONCompare.compareJSON(
44 | "[{id:1}, {id:3}, {id:5}]",
45 | "[{id:1}, {id:3}, {id:6}, {id:7}]", new ArrayOfJsonObjectsComparator(JSONCompareMode.LENIENT)
46 | );
47 |
48 | Assert.assertTrue(compareResult.failed());
49 | String message = compareResult.getMessage().replaceAll("\n", "");
50 | Assert.assertTrue(message, message.matches(".*id=5.*Expected.*id=6.*Unexpected.*id=7.*Unexpected.*"));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/test/java/org/skyscreamer/jsonassert/comparator/JSONCompareUtilTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | package org.skyscreamer.jsonassert.comparator;
16 |
17 | import junit.framework.Assert;
18 | import org.junit.Test;
19 |
20 | import java.util.ArrayList;
21 | import java.util.Collections;
22 | import java.util.List;
23 | import java.util.Map;
24 |
25 | /**
26 | * Test JSONCompareUtil
27 | *
28 | * @author Carter Page
29 | */
30 | public class JSONCompareUtilTest {
31 | @Test
32 | public void testGetCardinalityMap() {
33 | final int NUM_A = 76;
34 | final int NUM_B = 3;
35 | final int NUM_C = 0;
36 | final int NUM_D = 1;
37 | final int NUM_E = 2;
38 |
39 | List listToTest = new ArrayList(NUM_A + NUM_B + NUM_C + NUM_D + NUM_E);
40 | for (int i = 0; i < NUM_A; ++i) listToTest.add("A");
41 | for (int i = 0; i < NUM_B; ++i) listToTest.add("B");
42 | for (int i = 0; i < NUM_C; ++i) listToTest.add("C");
43 | for (int i = 0; i < NUM_D; ++i) listToTest.add("D");
44 | for (int i = 0; i < NUM_E; ++i) listToTest.add("E");
45 | Collections.shuffle(listToTest);
46 |
47 | Map cardinalityMap = JSONCompareUtil.getCardinalityMap(listToTest);
48 | Assert.assertEquals(NUM_A, cardinalityMap.get("A").intValue());
49 | Assert.assertEquals(NUM_B, cardinalityMap.get("B").intValue());
50 | Assert.assertNull(cardinalityMap.get("C"));
51 | Assert.assertEquals(NUM_D, cardinalityMap.get("D").intValue());
52 | Assert.assertEquals(NUM_E, cardinalityMap.get("E").intValue());
53 | }
54 | }
55 |
--------------------------------------------------------------------------------