Can HTTP requests be mocked by MockBox?

I’ve been working on a wrapper library for a REST API. After enough tests, I started to get frustrated with how long they were taking to run because of all the HTTP requests to the API for all the test cases.

I’m curious if MockBox is fit to mock a bunch of HTTP requests to test against.

I’ve tinkered with VCR, a Ruby gem where you define a URI, the test hits it once, serializes the complete response to a file, and then replays it again by reading in the file for all future requests. I was wondering if MockBox could be used for something like that, otherwise I thought about maybe writing a library to do something like I described.

-Dan

I don’t see why not. Sounds like a great addition.

Luis Majano
CEO
Ortus Solutions, Corp
www.ortussolutions.com
P/F: 1-888-557-8057
Direct: (909) 248-3408

ColdBox Platform: http://www.coldbox.org

ContentBox Platform: http://www.gocontentbox.org
Linked In: http://www.linkedin.com/pub/3/731/483

Social: twitter.com/ortussolutions | twitter.com/coldbox | twitter.com/lmajano | twitter.com/gocontentbox

Note, I don’t think there’s anyway to mock an actual tag (unless you’re using Railo where you can override tags).

You would need to abstract your http calls to the REST endpoint inside of method that could be mocked. Even if the method simply passed all it’s arguments directly along to CF’s native HTTP functionality.

At that point, wrapping that method in some kind of caching would be fairly trivial. In fact, there is even an AOP advice on ForgeBox called CacheBack that would probably work right out of the box.

http://www.coldbox.org/forgebox/type/wirebox-aspects

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Brad,

That is if you use CFHTTP, ColdBox could very easily if not already have that wrapped up, by convention that then could be mocked.

Andrew, I’m not aware of anything in the ColdBox core for abstracting HTTP calls. There were plugins for reading SOAP web services which have been moved to the cbfeeds module though

I think this would make an excellent module that registers a model with WireBox that can make HTTP calls with various options for caching. It would honestly be pretty simple. In addition to caching, you could even add configuration for straight-up mocking the response from remote URIs for the sake of writing a client for a REST API that doesn’t even exist yet.

Hmm, Luis does have the Relax module. I’m not sure it does any of this but maybe it should. Thing is, I think relax might only be for development purposes. If your REST client called an intermediate wrapper, it would need to be present in production as well. This functionality could also be useful to a wider audience than just REST API users, since hitting remote URIs with CFHTTP is a fairly common thing that people might want to mock or cache. (Home-brewed APIs, requesting remote images, screen scrapers, etc.)

The original question, of course, was if this could be done with MockBox. The main issue I see there is that would still assume the user of some intermediate abstraction around the CFHTTP tag which means the code would need to already be using some sort of library for the HTTP calls for it to be possible. That’s what makes me think that there should perhaps just be a general-purpose library for abstracting HTTP calls with caching or mocking capabilities outside of mockbox.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Oops, sorry. The SOAP functionality was moved into the cbsoap module, not the cffeeds module.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Yeah I wasn’t sure, I haven’t even looked at ColdBox 4.0 as yet. But I would imagine something like a wrapper for cfmail would not be hard to implement for cfhttp as well.

Thanks for everyone’s replies. Glad it generated some discussion and that it wasn’t something I was overlooking.

The VCR Ruby gem hooks into an HTTP mocking lib called WebMock (others are supported too). Thought I’d provide some reference from VCR below.

Ultimately, it looks like they tap into existing HTTP classes in Ruby as well as support for other HTTP classes. I don’t think we’d get that ability with ColdFusion. Railo maybe? So, yeah, maybe if there was a ColdBox general purpose HTTP wrapper to make your calls that could be used in code and in tests the same way, that might work best? I’m currently using a general function for HTTP calls in a base class that my other objects are inheriting from, but again - that’s no good if people are doing that a dozen different ways.

Seems reasonable to say “Make HTTP Calls with this ColdBox wrapper for consistency and testability.”

I’m not quite sure where I would start contributing something like that. I’m not familiar with coldbox-core or mockbox really either. I would imagine something like this would require extensions to ColdBox-core and MockBock.

VCR serializes the first initial HTTP response to a YAML file. Ruby community seems to really like YAML for stuff, but I think something like JSON would be fine too.

# spec/support/vcr_setup.rb
VCR``.configure ``do |c|
#the directory where your cassettes will be saved` c.cassette_library_dir = 'spec/vcr'` ```# your HTTP request service. You can also use fakeweb, webmock, and more` ```c.hook_into :typhoeus end`

# spec/model/your_model_spec.rb describe YourModel do` ```describe '#call_api’ do ```it "gets a response from an api" ``do
VCR``.use_cassette ``'model/api_response'` `do` response = call_api(api_url) ```response.first.should == "hello world"
end` end ```end
end

`

> Ultimately, it looks like they tap into existing HTTP classes in Ruby as well as support for other HTTP classes. I don’t think we’d get that ability with ColdFusion. Railo maybe?

On ColdFusion, No. On Railo, sort of-- but not programmatically. You’d have to install an extension or tag manually by copying some files. Such is the nature of a more “monolithic” type of architecture with everything built in far below the covers. FWIW, Railo is moving in the right direction here. Especially with the move to OSGI bundles in Railo 5 to start breaking up the core.

> Seems reasonable to say “Make HTTP Calls with this ColdBox wrapper for consistency and testability.”

I would agree, and I would encourage you to help author such a library :slight_smile:

> I’m not quite sure where I would start contributing something like that.

Just look at the ColdBox “core” modules. They’re all on GitHub under the “ColdBox” account. Each repo has a little MVC test app, but the actual module code is just in the modules/moduleName folder. For instance, here’s the MessageBox module that replaced the old MessageBox plugin:
https://github.com/ColdBox/cbox-messagebox/tree/master/modules/cbmessagebox

> I would imagine something like this would require extensions to ColdBox-core

No, actually you don’t have to touch the ColdBox core at all. In fact, that’s kind of the whole purpose of modules :slight_smile: All you’re doing is providing a model CFC that provides some utility to a developer. The simplest version of this could literally just be two files:

/modules/foobar/ModuleConfig.cfc
/modules/foobar/models/MyService.cfc

That it. The ModuleConfig wouldn’t even need any special configuration either. When the module is loaded, ColdBox will find MyService.cfc in the “models” convention and register “myService@foobar” automatically.

Then in your docs, you just tell people to do this in their code:

getInstance( ‘myService@foobar’ ).doSomethingCool();

That’s really it.

> would require extensions to ColdBox-core and MockBock.

So MockBox-- I think there’s a couple different thoughts here and I’m not sure they’re mutually inclusive.

  1. The first thought is that MockBox would have some functionality to mock HTTP requests, however that supposes the existence of some sort of known wrapper library.

  2. The second thought is for the actual wrapper library itself, which for all practical intents and purposes could include the ability to mock the response of a URI which makes me question if the MockBox component is even necessary.
    I think the biggest issue is that I can imagine at least two separate scenarios in which a developer might want to mock a remote endpoint:

  3. Needs to develop against an unreachable, incomplete, or non-existent remote URI. Would most likely be configured as an per-environment overridden setting just like the MailService settings allow you to send mail to a file only on your dev and stage server.

  4. Needs to seamlessly bypass actual HTTP call only when running code inside of a testing suite for the sake of speed and/or isolation of the SUT. The testing suite would either need to programmatically change settings on the fly, or apply a AOP aspect to the HTTP Service to intercept its calls.

Also, keep in mind that when we’re talking about ColdBox we have our full array of tools such as modules, model conventions, CacheBox, LogBox, etc at our disposal. However, MockBox is a standalone tool used by a lot of poor, misguided folk who haven’t found the light of ColdBox and, well, they’re pretty much out in the cold when it comes to standardized code reusability. Therefore, any Mockbox solution pretty much has to be written from scratch and capable of running standalone outside of any framework.

IMO, this is why the lack of modules as a first class citizen of the CFML engines and no singular wide-spread CFML framework is the bane of CF developers existence. We can build nice things, but the non-ColdBox people will never be able to use it-- but I digress…

> Ruby community seems to really like YAML for stuff, but I think something like JSON would be fine too.

My opinion (which assumes a ColdBox-centric module approach) is not to tie your implementation to ANY format. We built an awesome storage aggregator/API called CacheBox which allows you to store arbitrary data in any storage medium you with in a flexible and pluggable fashion. So, just set stuff in CacheBox and allow the dev to choose a cache storage in memory, database, Couchbase, Memcached, or yes, even a file. The format is really irrelevant unless you plan on reading the files. It might as well be base64 encoded binary as long as it just works.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Yes, the two scenarios are exactly the ones I had in mind here.

So it seems the way to go would be to have some sort of HTTP response representation object that would be returned from a custom HTTP object (ie: myHTTPService.init(args), makeHTTPRequest(args) ). I like the idea of making that it’s own library so it can mock itself i suppose? Maybe the object is init-ed with a mock flag or something to write the response to the file if it doesn’t exist, else read from the file to build the response?

I personally like the serialized flat file idea because it makes it dead simple to go in and edit accordingly. If the API does change, especially if it’s in development, you can make quick and easy changes and you’re not pulling in a major dependency for something quite as small.