Sorry if this is a newbie question, but I would really appreciate any ideas the community could offer regarding the problem I am having, with the following method that I have in Grails, LocationService.
Location locate(String target, String locator, Application app, boolean sync = true) { if (!target) throw new IllegalArgumentException("Illegal value for msid: " + target) def locRequest = Request.create(target, Type.LOCATE) if (!locRequest.save()) { return Location.error(target, "Error persisting location request") } locationSource.locateTarget(target, locator, app, sync) }
I have a domain class, Request, which, as well as default GORM methods, also have some additional domain methods, for example. create () method below
@EqualsAndHashCode class Request { String reference String msid Type type Status status Destination destination DateTime dateCreated DateTime dateCompleted static create(String msid, Type type, Destination destination = Destination.DEFAULT) { new Request(reference: reference(type), type: type, status: Status.INITIATED, dateCreated: new DateTime()) }
Finally, I have Spock's spec. I need to make fun of both the standard GORM methods and some stubs of some additional domain logic, for example, the static creation method, in order to return a valid object for saving in the test code.
Ideally, I would use Spock mocks, but I canβt use them here, because according to the message below from Peter N, they need to be entered into the caller, and in this case the Request (which I'm trying to make fun of) is created as a local variable in the location method in LocationService:
https://groups.google.com/forum/?fromgroups=#!topic/spockframework/JemiKvUiBdo
I also canβt use the Grails 2.x @Mock annotation as, although it will mock the GORM methods, I'm not sure that I can mock / stomp the additional static create () method from the Request class.
Therefore, finally, I tried to use the Groovy StubFor / MockFor methods to do this, since I believe that they will be used in the call to the testing method, wrapping it in a closure of use (as shown below),
Here is a test specification:
@TestFor(LocationService) // @Mock(Request) class LocationServiceSpec extends Specification { @Shared app = "TEST_APP" @Shared target = "123" @Shared locator = "999" def locationService = new LocationService() LocationSource locationSource = Mock() def "locating a valid target should default to locating a target synchronously"() { given: def stub = new StubFor(Request) stub.demand.create { target, type -> new Request(msid: target, type: type) } stub.demand.save { true } 1 * locationSource.locateTarget(target, locator, app, SYNC) >> { Location.create(target, point, cellId, lac) } def location when: stub.use { location = locationService.locate(target, locator, app) } then: location }
However, when I run the test, although the stubbed create method returns a Request stub, I get a failure in the stubbed save method:
groovy.lang.MissingMethodException: No signature of method: com.domain.Request.save() is applicable for argument types: () values: [] Possible solutions: save(), save(boolean), save(java.util.Map), wait(), last(), any()
Can someone please indicate what I'm doing wrong here, or suggest the best approach to solving my specific case, if you need to drown out additional methods, as well as GORM methods of the domain class, which I cannot enter directly into the test code?
Thanks in advance,
Patrick