Hello!

I felt the need to mock http api (like nock in node, that is, mock http request-response itself on low-level part, leaving aside the question of what wrapper / library one uses to get to that http; in node it mocks basic http layer, here I tackled ZnClient), but struggled for a time how to grasp it. Finally I used something like this (with help of Mocketry, `1 to: 10` to mean "enough to actually be used even if there are more unrelated uses", it could as well be `1 to: 100`):

  ZnClient stub new willReturnValueFrom:
    ((1 to: 10) collect: [ :i | ZnMockClient
      whenRequest: [ :request |
{ request uri scheme. request uri authority. request uri pathPrintString. request uri query associations asSet } = { #https. 'onesignal.com'. '/api/v1/players/{1}' format: { UUID fromString36: 'Q7' }. { 'app_id' -> appId } asSet }
          and: [ #(GET HEAD) includes: request method ] ]
      thenResponse: [ :request | ZnResponse ok: (ZnEntity json: '{}') ] ]).

with the help of this class (garbled utf not my fault, iceberg metacello integration does it):

'From Pharo6.0 of 13 May 2016 [Latest update: #60512] on 17 October 2017 at 12:05:38.908634 pm'!
ZnClient subclass: #ZnMockClient
        instanceVariableNames: 'conditionBlock responseBlock'
        classVariableNames: ''
        poolDictionaries: ''
        category: 'Towergame-Tests'!
!ZnMockClient commentStamp: 'HerbyVojcik 10/16/2017 16:43' prior: 0!
I am a mock ZnClient.

I am created with ZnMockClient whenRequest: whenBlock thenResponse: thenBlock.

Upon execution of the request, when (whenBlock cull: request) is true, response is set to (thenBlock cull: request). Otherwise, behaviour is delegated to super.!


!ZnMockClient methodsFor: 'accessing' stamp: 'HerbertVojčík 10/17/2017 12:00:27'!
conditionBlock
        ^ conditionBlock! !

!ZnMockClient methodsFor: 'accessing' stamp: 'HerbertVojčík 10/17/2017 12:00:27'!
responseBlock: anObject
        responseBlock := anObject! !

!ZnMockClient methodsFor: 'accessing' stamp: 'HerbertVojčík 10/17/2017 12:00:27'!
conditionBlock: anObject
        conditionBlock := anObject! !

!ZnMockClient methodsFor: 'accessing' stamp: 'HerbertVojčík 10/17/2017 12:00:27'!
responseBlock
        ^ responseBlock! !


!ZnMockClient methodsFor: 'private protocol' stamp: 'HerbertVojčík 10/17/2017 12:00:27'!
executeRequestResponse
        ^ (self conditionBlock cull: self request)
ifTrue: [ response := self responseBlock cull: self request. response contents ]
                ifFalse: [ super executeRequestResponse ]! !

"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!

ZnMockClient class
        instanceVariableNames: ''!

!ZnMockClient class methodsFor: 'instance creation' stamp: 'HerbertVojčík 10/17/2017 12:00:27'!
whenRequest: aBlock thenResponse: anotherBlock
        ^ self new
                conditionBlock: aBlock;
                responseBlock: anotherBlock;
                yourself! !

Question 1: Is there a better way?

Question 2: If not, would ZnMockClient be good addition to Zinc itself, to ease testing for others?

Herby

Reply via email to