Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing breeze application

I am doing an application with durandal, breeze, and knockout. I have started to implement some test. The first problem that I have had is to decide what I should test and what not. I know that I should test everything, but it is not always possible in a little company.

My second problem is how I can test my calls to the server. I have seen some information in the breeze page about testing. Also I have seen the DocCode example. But I would like to know more opinions about how I can do that.

My questions are:

  1. What do I should test in the breeze calls?
  2. I would like to test this, emulating the backend. Is it possible? Any example?
  3. Any advice or comment would be great
like image 629
jvrdelafuente Avatar asked Apr 30 '13 10:04

jvrdelafuente


1 Answers

Wow ... that's a big question!

There's is a little on this subject in the documentation. Not nearly enough to be sure.

I'm guessing that you are fairly new to JavaScript testing. If you've seen DocCode, you know that we use QUnit around here. Many prefer Jasmine, Mocha or something else; I can only speak to QUnit.

First step is learn QUnit. It's not hard. QUnit's own intro is good. I like Ben Alhman's slide deck.

Next I'd practice with small tests of your business logic that does NOT go over the wire. Could be any interesting logic in a ViewModel or perhaps some calculated property in a model (entity) object.

You can test a VM's interaction with a "DataContext" quite easily without going over the wire. Create a "FakeDataContext" and inject that into your tests instead of the real one. Alternatively you could "monkey patch" the real "DataContext" in strategic places that turn it into a fake.

When faking the DataContext, I find it useful to leverage Breeze's ability to confine queries to the local cache. The local cache serves as an in-memory surrogate for data that would otherwise have been retrieved from the server.

This can be as simple as setting the FetchStrategy of the manager's default QueryOptions ... perhaps like this

var queryOptions = new QueryOptions({ 
    mergeStrategy: MergeStrategy.PreserveChanges, 
    fetchStrategy: FetchStrategy.FromCache 
});

var entityManager = new EntityManager({ 
    serviceName: "yourEndpoint", 
    queryOptions: queryOptions
});

Now your queries will all be directed to the cache (unless they have an explicit QueryStrategy of their own).

Now make it useful by populating the cache with test data. There are numerous examples of faked entities in DocCode. Here's an example of a faked Customer:

   var testCustomer = manager.createEntity('Customer', {
       // test values
       CustomerID: testCustomerID,
       CompanyName: testCustomerName,
       ...
    }, breeze.EntityState.Unchanged); // as if fetched from the database

If I need the same test data repeatedly, I write a "Data Mother" that populates an EntityManager with test data for me.

I can do a lot of testing this way without ever hitting the server. The whole time I'm working with the Breeze entities in JavaScript ... much as I do in production code. I don't have to learn a mocking library or inject another tool.

Another approach - harder, lower level, but more powerful - is to replace the Breeze default AJAX adapter with a fake that returns test JSON values as if they had come from the server. You can use a tool like Fiddler to make fake JSON from actual payload snapshots. You can also use this trick for simulating server-side save behavior.

Update 3 May 2013

The DocCode Sample includes a new TestAjaxAdapter for simulating server responses as I just described. Check out the testAjaxAdapter.js and see how to use it in testAjaxAdapterTests.js. This particular version of DocCode is only on GitHub right now but it will be published officially in the release immediately after v.1.3.2.

... end of update; back to original post ...

Does faking the JSON stream within your fake AJAX adapter seem like too much of a PITA? Break out your mad Breeze skills and write a custom JsonResultsAdapter to create those fakes. Have your fake AJAX adapter return an empty array for every query request. Then you can do anything you want in the extractData and visitNode methods of your JsonResultsAdapter.

I trust it is obvious that you can fake your server-side controller too. Of course your tests will still make trips "over the wire" to reach that controller.

Hope these clues are sufficient to get you headed in a satisfactory direction.

Update 30 April 2013

Breeze will need metadata to do its thing. Your metadata comes from the server. Calling the server for metadata would seem to defeat the purpose of running tests entirely disconnected.

So true. Now I'm not a stickler on this point. I don't mind hitting the server for metadata at the top of a test module ... exactly once ... and then running the rest of my tests without going to the server for metadata. But if you're a purist or you just don't want to do that, you can write the server-side metadata to a JavaScript file on the server and load that script statically on your test runner's HTML page just like any other script.

For an example of this technique, look at App_Data/WriteMetadataScriptFiles.cs which generates a JavaScript file for the Northwind model in the forthcoming (later this week) v.1.3.2 DocCode sample. The DocCode tests load JavaScript files dynamically with require.js. The metadataTests.js test file shows how to load the generated northwindMetadata.js with require. You don't have to be that clever if you're not using require.js.

Note to self: write some samples illustrating these techniques.

like image 166
Ward Avatar answered Nov 15 '22 13:11

Ward