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

Provide better diagnostics when a descriptor is missing a property required by the snippet template #678

Open
FloHin opened this issue Apr 3, 2020 · 4 comments

Comments

@FloHin
Copy link

FloHin commented Apr 3, 2020

Background: I removed some method calls to "description()" to better debug my Rest tests, big mistake.

Now I understand the exception, but I needed to debug it, to understand that not the "description" of my entity was meant, but that "FieldDescriptor for path '$my_variable_name' has no description"

UseCase: As a developer, I want the exception to show me what field exactly is meant.

I understand that this is not a "bug report", but merely a minor proposal to improve "developer happiness", as it took me really a long time to figure out what was wrong

Reproduce:

Instead of

...
fieldWithPath(prefix + "input_data_type").type(JsonFieldType.STRING).description("DataType for input data")
...

forget the description

...
fieldWithPath(prefix + "input_data_type").type(JsonFieldType.STRING)
...

Exception:

No key, method or field with name 'description' on line 7
org.springframework.restdocs.mustache.MustacheException$Context: No key, method or field with name 'description' on line 7
	at org.springframework.restdocs.mustache.Mustache$VariableSegment.execute(Mustache.java:789)
	at org.springframework.restdocs.mustache.Template$1.execute(Template.java:131)
	at org.springframework.restdocs.mustache.Template$1.execute(Template.java:124)
	at org.springframework.restdocs.mustache.Template$Fragment.execute(Template.java:59)
	at org.springframework.restdocs.templates.mustache.AsciidoctorTableCellContentLambda.execute(AsciidoctorTableCellContentLambda.java:36)
	at org.springframework.restdocs.mustache.Mustache$SectionSegment.execute(Mustache.java:856)
	at org.springframework.restdocs.mustache.Mustache$BlockSegment.executeSegs(Mustache.java:827)
	at org.springframework.restdocs.mustache.Mustache$SectionSegment.execute(Mustache.java:848)
	at org.springframework.restdocs.mustache.Template.executeSegs(Template.java:114)
	at org.springframework.restdocs.mustache.Template.execute(Template.java:91)
	at org.springframework.restdocs.mustache.Template.execute(Template.java:82)
	at org.springframework.restdocs.templates.mustache.MustacheTemplate.render(MustacheTemplate.java:62)
	at org.springframework.restdocs.snippet.TemplatedSnippet.document(TemplatedSnippet.java:82)
	at org.springframework.restdocs.generate.RestDocumentationGenerator.handle(RestDocumentationGenerator.java:191)
	at org.springframework.restdocs.mockmvc.RestDocumentationResultHandler.handle(RestDocumentationResultHandler.java:52)
	at org.springframework.test.web.servlet.MockMvc$1.andDo(MockMvc.java:201)
	at com.mlreef.rest.api.DataProcessorApiTest.Can retrieve all DataProcessors filtered(DataProcessorApiTest.kt:110)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:532)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:171)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:167)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:114)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:59)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:108)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$4(NodeTestTask.java:112)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:72)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:98)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:74)
@FloHin
Copy link
Author

FloHin commented Apr 3, 2020

If maintainers think this is a good idea, I would fork and work on that, happy to contribute.

@wilkinsona
Copy link
Member

Thanks for reporting this, @FloHin. There's definitely room for improvement here. Thanks to the flexibility of the template-based approach, I'm not sure how precisely the problem can be described. However, I'm pretty sure that it could be better than it currently is. If you have some time to work on some improvements, a pull request would be great. Thanks!

@wilkinsona
Copy link
Member

Unfortunately, when a failure like this occurs, JMustache does not provide enough information to identify exactly which field did not have a description. The best that can be done is to provide a little bit more context, including the template that was being rendered, when the failure occurred. Something like this:

org.springframework.restdocs.templates.TemplateRenderingException: Failed to render 'request-fields'. No value for 'description' on line 7:

  1. |===
  2. |Path|Type|Description
  3. 
  4. {{#fields}}
  5. |{{#tableCellContent}}`+{{path}}+`{{/tableCellContent}}
  6. |{{#tableCellContent}}`+{{type}}+`{{/tableCellContent}}
  7. |{{#tableCellContent}}{{description}}{{/tableCellContent}}
  8. 
  9. {{/fields}}
 10. |===

	at org.springframework.restdocs.templates.mustache.MustacheTemplate.render(MustacheTemplate.java:95)
	at org.springframework.restdocs.snippet.TemplatedSnippet.document(TemplatedSnippet.java:82)
	at org.springframework.restdocs.payload.RequestFieldsSnippetTests.missingDescription(RequestFieldsSnippetTests.java:58)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runners.Suite.runChild(Suite.java:128)
	at org.junit.runners.Suite.runChild(Suite.java:27)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: org.springframework.restdocs.mustache.MustacheException$Context: No key, method or field with name 'description' on line 7
	at org.springframework.restdocs.mustache.Mustache$VariableSegment.execute(Mustache.java:789)
	at org.springframework.restdocs.mustache.Template$1.execute(Template.java:131)
	at org.springframework.restdocs.mustache.Template$1.execute(Template.java:124)
	at org.springframework.restdocs.mustache.Template$Fragment.execute(Template.java:59)
	at org.springframework.restdocs.templates.mustache.AsciidoctorTableCellContentLambda.execute(AsciidoctorTableCellContentLambda.java:36)
	at org.springframework.restdocs.mustache.Mustache$SectionSegment.execute(Mustache.java:856)
	at org.springframework.restdocs.mustache.Mustache$BlockSegment.executeSegs(Mustache.java:827)
	at org.springframework.restdocs.mustache.Mustache$SectionSegment.execute(Mustache.java:848)
	at org.springframework.restdocs.mustache.Template.executeSegs(Template.java:114)
	at org.springframework.restdocs.mustache.Template.execute(Template.java:91)
	at org.springframework.restdocs.mustache.Template.execute(Template.java:82)
	at org.springframework.restdocs.templates.mustache.MustacheTemplate.render(MustacheTemplate.java:84)
	... 34 more

@wilkinsona
Copy link
Member

It may be possible to improve on the above using a Lambda or by implementing CustomContext. Both will require changes that are too broad for a 2.0.x release.

@wilkinsona wilkinsona changed the title Misleading exception when FieldDescriptor does not have a "description()" Provide better diagnostics when a descriptor is missing a property required by the snippet template Sep 2, 2020
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

3 participants