I’m really interested in BreezeJS right now. It seems like a really promising new open source (MIT License) framework for helping you get data into your JavaScript applications, including single page applications (which are coming to be known by the acronym SPA).
Breeze has lots of features. One to whet your appetite is the query syntax:
BreezeJS Queries
var query = new breeze.EntityQuery() .from("Employees") .where("LastName", "startsWith", "P") .orderBy("LastName"); |
I’m attracted to the fluent aproach; and to the idea that you can build up queries client side that interact intelligently with a back end. Under the covers, this filter is being passed to a remote facade that can interpret the query – we aren’t downloading all of /api/Employees/ to do this. Breeze achieves this by interacting with remote OData endpoints.
Note |
OData According to Wikipedia, the Open Data Protocol (a.k.a OData) is a data access protocol from Microsoft. It is similar to JDBC and ODBC although OData is not limited to SQL databases. OData is built on the Atom Publishing Protocol and JSON where the Atom structure is the envelope that contains the data returned from each OData request. An OData request uses the REST model for all requests. |
I’d like to explore using BreezeJS with a JVM language. There is a Java library for producing and consuming OData called odata4j which I’m excited about. It’s my practice to start with a failing test – so step one is to get Breeze in a working test harness. If this goes well, we’ll keep going and try to connect it with odata4j. Though the Breeze project uses qunit, I’ve heard good things about Mocha. Early tests indicate that BreezeJS references window, so I’ll need something like mocha-phantomjs. The mocha-phantomjs GitHub readme talks about using a project called ChaiJS for assertions, so I’ll pull that in as well. The steps I used to get mocha up and running with breeze are below. While I don’t intend to use NodeJS in this tutorial, it seems like the quickest way to get Mocha going is to use Node’s npm package manager.
Installing Mocha And Breeze Dependencies
brew install phantomjs brew install node mkdir lib; cd lib npm install mocha npm install chai npm install q npm install mocha-phantomjs |
Breeze can’t be installed via npm, of course. The BreezeJS project has put a lot of effort in to making sure that the nuget path works smoothly, but I don’t have nuget on my Mac. There is a zip file to download, however, if you check their download page. I downloaded runtime 0.85.2, and unzipped it.
Installing BreezeJS
mkdir breezejs cd breezejs wget http://www.breezejs.com/sites/all/packages/breeze-runtime-0.85.2.zip unzip breeze-runtime-0.85.2.zip rm -Rf WebApi/ |
Assembling the Test Harness
Let’s start with a test runner and a bare bones test that proves that we can access Breeze. Here’s my working test-runner:
Test Runner test/JavaScript/test-runner.html
<html> <head> <meta charset="utf-8"> <link rel="stylesheet" href="../../lib/node_modules/mocha/mocha.css" /> </head> <body> <div id="mocha"></div> <!-- infrastructure and dependencies --> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js" ></script> <script type="text/javascript" src="../../lib/node_modules/mocha/mocha.js" ></script> <script type="text/javascript" src="../../lib/node_modules/chai/chai.js" ></script> <script type="text/javascript" src="../../lib/node_modules/q/q.js" ></script> <script type="text/javascript" src="../../lib/breezejs/Scripts/breeze.js" ></script> <!-- setting up mocha and chai --> <script type="text/javascript"> mocha.ui('bdd'); mocha.reporter('html'); expect = chai.expect; assert = chai.assert; </script> <!-- include our specifications --> <script type="text/javascript" src="breeze-dependencies.js"></script> <script type="text/javascript" src="TestNetflixClient.js"></script> <!-- run the tests --> <script type="text/javascript"> if (window.mochaPhantomJS) { mochaPhantomJS.run(); } else { mocha.run(); } </script> </body> </html> |
Specification test/JavaScript/breeze-dependencies.js
describe('NetflixClient', function() { it('should be able to use BreezeJS', function() { var manager = new breeze.EntityManager({ serviceName: "http://odata.netflix.com/v2/Catalog/" }); var query = breeze.EntityQuery.from("Products"); return manager.executeQuery(query); }) }); |
An astute reader will notice that this test doesn’t do much, it just makes sure that we have Breeze in a harness. Now, we can run this test on the command line like so to see if our tests pass.
$ mocha-phantomjs test/JavaScript/test-runner.html NetflixClient ✓ should be able to use BreezeJS 1 test complete (18 ms) |
Excellent! We have a workable test environment.
Tip |
Debugging To get the test-runner set up how I wanted, I often opened it in Chrome so that I could read the console to help troubleshoot issues. This worked fine with one exception: BreezeJS is trying to make XmlHttpRequests back to a live OData endpoint, but you’ve loaded the page from a file:// URL. In this case, your origin is null, and Chrome’s CORS rules prevent you from accessing the endpoint. While it would be a really bad idea to do this all the time, when you need debugging you can start Chrome with this command to alleviate this issue: |
open -a Google\ Chrome --args --disable-web-security -–allow-file-access-from-files |
Note |
You can find the source code of this example on GitHub. |
Breeze only uses ‘window’ to find libraries that load themselves in the global namespace. f you’re in Node you should be able to alias ‘global’ as ‘window’ and move on.
Thanks Ward. I’m learning a lot about Mocha and BreezeJS as I go! I don’t mind using PhantomJS, I normally use it with Jasmine. I wasn’t imagining a NodeJS based testing system – but it’s nice to know that’s there as I try to refactor this to make it more elegant.
Awesome! An alternative for a long-neglected upshot. And with testing framework!
Now how it will work with Continuous Integration? Scraping test pages and asserting on the content looks like a sufficiently lazy approach.
yep! also its also fairly easy to wire up mock responses and do proper unit tests. hoping to get in to that in the next post.
Reblogged this on happy && coding.
This is not a TDD or unit test by the way. This is an example of functional testing. I just wanted to warn the readers because if I was seeing these for the first time, I could implement them wrongly.