-
Notifications
You must be signed in to change notification settings - Fork 0
Groovy unit tests
This article contains the experience gained in the process of Groovy scripts development. Due to the specifics of the project the only libraries for testing our team could use were JUnit + Mockito. Here you can find different ways of mocking in Groovy scripts tests which can help you to write effective unit tests. All 3 methods can be combined in one test if it is necessary. The first and the second methods allow to mock Java classes and the third one - Groovy classes.
This way of mocking can be used if you have any third party JAVA classes in your lepContext. It should be mentioned that using Mockito in Groovy is not much different from using in Java and you can use all your previous experience with Mockito. All the third party classes can be mocked with @Mock annotation as in JAVA. E.g.:
@Mock
private AddressService addressService
After providing this mock with the appropriate way to your test lepContext it can be used like in JAVA:
when(addressService.findOne(any())).thenReturn...
...
verify(addressService).save(any())
This method is enabled for java.lang.Class classes and can be used for mocking objects which are initialized in the tested class and are not able to be tested with Mockito. For example the field of the class:
RestTemplate restTemplate = new RestTemplate()
is unable to be mocked with Mockito.
In this case we can use a special MetaClass which allows to dynamically add methods, constructors, properties and static methods using a neat closure syntax.
E.g.:
RestTemplate.metaClass.exchange = { url, method, requestEntity, responseType ->
new ResponseEntity<>(buildResponse(), HttpStatus.OK)
}
This example shows how to redefine the implementation of method exchange. Also such way of mocking works for static methods:
Library.metaClass.static.getAll << { def context-> [] }
The weak side of this way of mocking is necessity to remove the changes that were done to meta-class in the GroovyMetaClassRegistry:
GroovySystem.metaClassRegistry.setMetaClass(RestTemplate, null)
Otherwise those changes would be persistent across test method calls.
For more information see: https://groovy-lang.org/testing.html#testing_guide_emc
MockFor is a mocking class from the Groovy library. It can be found in package: groovy.mock.interceptor package. This class can be used for mocking Groovy classes in the same way as Mockito allows mocking Java classes but in lager number of cases. To create a mock with MockFor class you need to define it:
MockFor httpRequestService = new MockFor(HttpRequestService)
where HttpRequestService is your Groovy class. After that you need to describe methods which are needed to be redefined:
httpRequestService.demand.post(1..2) { String url, Object body, Object... params ->
return new ResponseEntity([:], HttpStatus.OK)
}
where post - is a method from HttpRequestService class. Numbers in brackets define the count of method calls. You can redefine static or private methods in the same way. MockFor is able to mock them. By default the describing of the method means that this method is going to be executed at least once (like verify in Mockito). After that the testing logic is passed to use which enables the mocking functionality
httpRequestService.use {
...
//logic to execute
...
}
Also you can verify the input parameters directly in method definition (like ArgumentCaptor in Mockito ):
httpRequestService.demand.post(1..2) { String url, Object body, Object... params ->
assert url == 'http://test'
assert body == [id:1]
return new ResponseEntity([:], HttpStatus.OK)
}