Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression in the Grails 4.0.6 calling response.json in Specification #253

Open
4 tasks done
longwa opened this issue Jan 7, 2021 · 5 comments
Open
4 tasks done

Comments

@longwa
Copy link

longwa commented Jan 7, 2021

When calling response.json in a Specification to test a RestfulController that respond with an empty list, an error occurs if you have created a default /object/_object.gson view such as:

model {
    Object object
}
json g.render(object)

Condition failed with Exception:

response.json.size() == 0
|        |
|        org.grails.web.converters.exceptions.ConverterException: Error parsing JSON
|        	at grails.converters.JSON.parse(JSON.java:260)
|        	at org.grails.plugins.testing.AbstractGrailsMockHttpServletResponse.getJson(AbstractGrailsMockHttpServletResponse.groovy:93)
|        	at example.FooControllerSpec.test something(FooControllerSpec.groovy:20)
|        Caused by: org.grails.web.json.JSONException: Missing value. at character 0 of 
|        	at org.grails.web.json.JSONTokener.syntaxError(JSONTokener.java:481)
|        	at org.grails.web.json.JSONTokener.nextValue(JSONTokener.java:358)
|        	at grails.converters.JSON.parse(JSON.java:251)
|        	... 2 more
<org.grails.plugins.testing.GrailsMockHttpServletResponse@379efd4e outputStreamAccessAllowed=true writerAccessAllowed=true characterEncoding=ISO-8859-1 charset=false content= outputStream=org.springframework.mock.web.MockHttpServletResponse$ResponseServletOutputStream@18b06b writer=null contentLength=0 contentType=application/json bufferSize=4096 committed=false locale=en_US cookies=[] headers=[Content-Type:[application/json]] status=200 errorMessage=null forwardedUrl=null includedUrls=[]>

Without the default GSON view, it works ok.

If you change the grails version to 4.0.5, the test will pass successfully, so this seems to be a regression in 4.0.6.

Task List

  • Steps to reproduce provided
  • Stacktrace (if present) provided
  • Example that reproduces the problem uploaded to Github
  • Full description of the issue provided (see below)

Steps to Reproduce

Download the sample application and run:

The key is to call respond for a JSON format without an explicit GSON view to render.

Expected Behaviour

response.json should succeed and essentially return empty (size == 0) as it does in 4.0.5.

Actual Behaviour

An error occurs when JSON.parse() is called b/c the output stream has an empty string instead of empty array syntax: "" vs "[]". This seems to be a result of the _object.gson being used, which causes the renderer to follow a different path.

Environment Information

  • Operating System: macOS 10.15.7
  • Grails Version: 4.0.6
  • JDK Version: zulu-1.8_275

Example Application

@xqliu
Copy link

xqliu commented Jan 14, 2021

This error happens also for our application which is on 4.0.5 currently, most of the tests depends on response.json breaks due to this issue.

Haven't had time look into this issue.

@puneetbehl puneetbehl transferred this issue from grails/grails-core Feb 1, 2021
@puneetbehl puneetbehl changed the title Regression in 4.0.6 calling response.json in Specification Regression in the Grails 4.0.6 calling response.json in Specification Feb 1, 2021
@puneetbehl
Copy link
Contributor

This is happening because of the change in #235 which now correctly sets the ModelAndViews in the request attributes. But, we also removed the following line from the DefaultViewRender:

render(view, request, response) 

We removed this to avoid calling the render method from multiple places because after setting the ModelAndView request attribute, the render is also called via DispatcherServlet ( which is not the case with unit test).

Right now, I am not sure what would be the fix for this but I will spend some more time next week figure out a solution.

@amadfida
Copy link

amadfida commented Feb 2, 2021

@puneetbehl we got hit with this as well when we upgraded grails-view to 2.0.4 - any workaround available as its failing a lot of our test. In addition do you know if its only effecting unit tests?

@puneetbehl
Copy link
Contributor

@amadfida Yes, it should only affect unit tests because the DispatcherServlet is not executed during the same.

@sbglasius
Copy link

sbglasius commented Oct 7, 2021

I have created this trait to work around this issue:

/**
 * Due to a change in Grails DefaultViewRenderer it does no longer do the actual view rendering to the response
 * thus leading to errors in ControllerUnitTests that expect the response being fully written.
 * See https://github.com/grails/grails-views/commit/25cab090bfaf6d2264b264c7248680b4f611c806#diff-bab08f900cdc8789160b7e74825cf68433382be9d9a632842136ad2fd91dd46c
 * 
 * Calling renderGsonView() after calling the controller in the unit-test will fix this issue. Not super pretty, but it works.
 */
trait JsonControllerUnitTest implements GrailsWebUnitTest {
    void renderGsonView() {
        ModelAndView modelView =(request.getAttribute(GrailsApplicationAttributes.CONTROLLER) as Controller)?.modelAndView
        modelView?.view?.render(modelView?.model, request, response)
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants