-
-
Save jeffsheets/ada3de8fe4a536e5351b to your computer and use it in GitHub Desktop.
import groovy.json.JsonSlurper | |
import org.springframework.test.web.servlet.MockMvc | |
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.* | |
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; | |
import static org.springframework.http.HttpStatus.* | |
import spock.lang.Specification | |
/** | |
* A Spock Spring MVC Rest unit test that doesn't require a full spring context | |
*/ | |
class AccountControllerTest extends Specification { | |
def accountController = new AccountController() | |
def securityService = Mock(SecurityService) | |
//The magic happens here | |
MockMvc mockMvc = standaloneSetup(accountController).build() | |
def setup() { | |
accountController.securityService = securityService | |
} | |
def "getAccount test hits the URL and parses JSON output"() { | |
when: 'rest account url is hit' | |
def response = mockMvc.perform(get('/rest/account')).andReturn().response | |
def content = new JsonSlurper().parseText(response.contentAsString) | |
then: 'securityService correctly returned account in JSON' | |
1 * securityService.getCurrentLogin() >> 'spockUser' | |
//Testing the HTTP Status code | |
response.status == OK.value() | |
//Showing how a contains test could work | |
response.contentType.contains('application/json') | |
response.contentType == 'application/json;charset=UTF-8' | |
//Can test the whole content string that is returned | |
response.contentAsString == '{"username":"spockUser"}' | |
//Or can use the JsonSlurper version to test the JSON as object | |
content.username == 'spockUser' | |
} | |
def "simple getAccount test without spring mvc json framework"() { | |
when: 'getAccount is called' | |
def result = accountController.getAccount() | |
then: 'securityService correctly returns account' | |
1 * securityService.getCurrentLogin() >> 'spockUser' | |
result.username == 'spockUser' | |
} | |
} |
awesome, that is great to hear!
Hello.
Is there way to check conditions for MockMVC before checking interaction with injected service (securityService
in this case)?
i.e. I don't want to see error message indicating that there was no interactions with securityService
, because there was an error e.g. parsing JSON POSTed to controller - I want to check if the response status is OK first.
@iborisov in that case I would wildcard the securityService interaction to basically just stub it out like this:
_ * securityService.getCurrentLogin() >> 'spockUser'
this won't verify that getCurrentLogin() is ever called, but that could be okay for your purposes
This is great! Thanks!
Where das "standaloneSetup" come from? Used the static imports you had but they dont really work
Thanks great example!!!
xetra11 MockMvcBuilders have standaloneSetup...
great example
Can you do an example with params?
Condition failed with Exception:
mvc.perform(get('/api/cards/token').params(requestParams)) .andExpect(status().isOk()) .andReturn() .response
| | | |
| | | jdk.proxy3.$Proxy66@32f5928a (renderer threw UnsupportedOperationException)
| | java.lang.reflect.InvocationTargetException
| | at org.codehaus.groovy.vmplugin.v9.Java9.of(Java9.java:160)
| | at org.codehaus.groovy.vmplugin.v9.Java9.getInvokeSpecialHandle(Java9.java:179)
| | at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
| | at org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder.params(MockHttpServletRequestBuilder.java:387)
| | at controller.CardControllerSpec.get Card Token - 200(CardControllerSpec.groovy:35)
| | Caused by: java.lang.IllegalAccessException: module jdk.proxy3 does not open jdk.proxy3 to unnamed module @10d307f1
| | at java.base/java.lang.invoke.MethodHandles.privateLookupIn(MethodHandles.java:259)
| | ... 5 more
| <org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder@1d416d7c method=GET url=/api/cards/token contextPath= servletPath= pathInfo= secure=null principal=null session=null characterEncoding=null content=null contentType=null headers=[:] parameters=[:] queryParams=[:] cookies=[] locales=[] requestAttributes=[:] sessionAttributes=[:] flashAttributes=[:] postProcessors=[]>
<org.springframework.test.web.servlet.MockMvc@567831a4 servlet=org.springframework.test.web.servlet.TestDispatcherServlet@271c374b filters=[] servletContext=org.springframework.mock.web.MockServletContext@3c9e187f defaultRequestBuilder=null defaultResponseCharacterEncoding=null defaultResultMatchers=[] defaultResultHandlers=[]>
@Jason-Terry unfortunately i don't have access to this project anymore, so i won't be able to easily try it out... In theory what you have here should work, so I don't know why it isn't working off the top of my head
I did figure it out. It was not a request parameter we were using, just confusingly handling authentication.
Now I am battling IntelliJ and its autocomplete. I can't get my code to behave when using JSON-slurper...
Code compiles, test runs and passes, but IDE doesn't understand content.response.results[0].last4 == 1234
Seems not to know what the methods are.
Thanks, very helpful gist. I used it as a base for spock unit tests in my template project for API/microservice development (java+springmvc+spock+embedded jetty+heroku) https://github.com/zedar/java-springmvc-heroku-template