////
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
////

Although generally testing can be done using functional tests via an HTTP client, the JSON views plugin also provides a trait which helps in writing either unit or integration tests.

To use the trait import the `grails.plugin.json.view.test.JsonViewTest` class and apply it to any Spock or JUnit test:

[source,groovy]
import grails.plugin.json.view.test.*
import spock.lang.Specification
class MySpec extends Specification implements JsonViewTest {
    ...
}

The trait provides a number of different `render` method implementations that can either render a JSON view found in `grails-app/views` or render an inline String. For example to render an inline template:

[source,groovy]
----
void "Test render a raw GSON view"() {
    when:"A gson view is rendered"
    JsonRenderResult result = render '''
        model {
            String person
        }
        json.person {
            name person
        }
''', [person:"bob"] <1>

    then:"The json is correct"
    result.json.person.name == 'bob' <2>
}
----

<1> Use the `render` method to return a `JsonRenderResult` passing in a String that is the inline template and a map that is the model
<2> Assert the parsed JSON, represented by the `json` property, is correct

To render an existing view or template use named arguments to specify an absolute path to either a template or a view:

[source,groovy]
----
when:"A gson view is rendered"
def result = render(template: "/path/to/template", model:[age:10])

then:"The json is correct"
result.json.name == 'Fred'
result.json.age == 10
----

If you are writing a unit test, and the model involves a domain class, you may need to add the domain class to the `mappingContext` object in order for it to be rendered correctly:

[source,groovy]
----
when:"A gson view is rendered for a domain class"
mappingContext.addPersistentEntity(MyDomain)
def result = render(template: "/path/to/template", model:[myDomain:MyDomain])

then:"The json is correct"
result.json.name == 'Fred'
result.json.age == 10
----

NOTE: Links generated by json views in a unit test may not match what they would normally generate in the standard environment. To fully test links, use a functional test.

== New Testing Framework

Since the release of json views, a new testing framework was released for Grails. A new trait has been developed that works with the new testing framework that is designed to replace the existing trait. The existing trait will be left as is for backwards compatibility.

The new trait works exactly the same way as the old one, however since the new trait is designed to work with the new framework, there are several benefits you can take advantage of. The first is configuration. In the old trait the application configuration was not included in the template engine, which had the potential to produce incorrect results. Other benefits include extensibility and features like `@OnceBefore`.

To get started, add the `org.apache.grails:grails-testing-support-views-gson` dependency to your project and implement the link:{api}grails/views/json/test/JsonViewUnitTest.html[JsonViewUnitTest] trait in your test instead of `JsonViewTest`.

NOTE: The new testing trait, like the testing framework, requires Spock.
