Does anyone know a way to use doh to test if an object is subscribed to a specific topic?
I am struggling to find any docs desccribing this type of test.
The reason that I am asking this is becuase when I construct my widget I subscribe it to a topic. I wanted to have a unit test that tests if the widget always has that topic subscription after its construction.
My topic has a private variable that I use as the topic string when creating the subscription.
So for example here is a topic called "CustomTopic":
define([], function(){
var topicString= "topicString";
return {
TOPIC_STRING: function(){
return topicString;
}
}
})
and the constructor in my widget looks like:
constructor: function() {
topic.subscribe(CustomTopic.TOPIC_STRING(), function(params) {doSomething(params)});
}
So you can see how easy it would be to check for the topic subscription against the private variable value, if I could just figure out how to see all subscriptions my widget has?
For reference:
Dojo 1.8 docs
Dojo's test util "doh" docs
I suggest your testing will be more robust / useful if it concentrates on behaviour as opposed to implementation. In this case, it would make more sense to test if your widget responds to the topic (or better still, the event that causes the topic to be published, for more of an integration test) rather than attempting to catch the subscription itself.
Of course, you could try and wrap topic.subscribe (bad thing), or inspect your widget's private list of handles (another bad thing). Incidentally, I hope you are in fact saving the handle returned by topic.subscribe so that you can remove (previously, unsubscribe) it later when the object is destroyed.
Better than those would be to simply make a new object, publish to that topic, and see if doSomething is called, or if the desired result has occurred. While doh does not provide support for listening to function calls, dojo/aspect is ideal for this purpose. So you might have something like this :
var myWidget = new myWidget(); // presumably subscription happened,
// but we only care about later behaviour
var somethingDone = false;
aspect.after(window, "doSomething", function(){somethingDone = true;});
topic.publish(CustomTopic.TOPIC_STRING());
doh.assertTrue(somethingDone);
In fact, I assume doSomething is not a global method, so you'll have to scope that properly, but otherwise this should work fine. Currently topic.publish is synchronous, so this should work fine, but it could become async in the future, in which case you would want to avoid calling doh.assertTrue until some later stage.
Related
I tried to understand difference between sinon library's fake, spy, stub and mock but not able to understand it clearly.
Can anybody help me to understand about it?
Just for understanding purpose call:
FuncInfoCollector = is a Function that records arguments, return value, the value of this(context) and exception thrown (if any) for all of its calls.
(this FuncInfoCollector is dummy name given by me, it is not present in SINON lib)
Fake = FuncInfoCollector + can only create a fake function. To replace a function that already exists in the system under test you call sinon.replace(target, fieldname, fake). You can wrap an existing function like this:
const org = foo.someMethod;
sinon.fake((...args) => org(...args));
A fake is immutable: once created, the behavior can't be changed.
var fakeFunc = sinon.fake.returns('foo');
fakeFunc();
// have call count of fakeFunc ( It will show 1 here)
fakeFunc.callCount;
Spy = FuncInfoCollector + can create new function + It can wrap a function that already exists in the system under test.
Spy is a good choice whenever the goal of a test is to verify something happened.
// Can be passed as a callback to async func to verify whether callback is called or not?
const spyFunc = sinon.spy();
// Creates spy for ajax method of jQuery lib
sinon.spy(jQuery, "ajax");
// will tell whether jQuery.ajax method called exactly once or not
jQuery.ajax.calledOnce
Stub = spy + it stubs the original function ( can be used to change behaviour of original function).
var err = new Error('Ajax Error');
// So whenever jQuery.ajax method is called in a code it throws this Error
sinon.stub(jQuery, "ajax").throws(err)
// Here we are writing assert to check where jQuery.ajax is throwing an Error or not
sinon.assert.threw(jQuery.ajax(), err);
Mock = Stub + pre-programmed expectations.
var mk = sinon.mock(jQuery)
// Should be called atleast 2 time and almost 5 times
mk.expects("ajax").atLeast(2).atMost(5);
// It throws the following exception when called ( assert used above is not needed now )
mk.expects("ajax").throws(new Error('Ajax Error'))
// will check whether all above expectations are met or not, hence assertions aren't needed
mk.verify();
Please have a look at this link also sinon.replace vs sinon.stub just to replace return value?
Just to add some more info to the otherwise good answer, we added the Fake API to Sinon because of shortcomings of the other original APIs (Stub and Spy). The fact that these APIs are chainable led to constant design issues and recurring user-problems and they were bloated to cater to quite unimportant use cases, which is why we opted for creating a new immutable API that would be simpler to use, less ambiguous and cheaper to maintain. It was built on top of the Spy and Stub Apis to let Fakes be somewhat recognizable and have explicit method for replacing props on objects (sinon.replace(obj,'prop',fake)).
Fakes can essentially be used anywhere a stub or spy can be used and so I have not used the old APIs myself in 3-4 years, as code using the more limited fakes is simpler to understand for other people.
So I have this decorate function that takes an object and a method-name and wraps it with external logic.
function decorate(object, methodName) {
var originalMethod = object[methodName];
object[methodName] = function () {
// pre-logic
var retVal = originalMethod.apply(this, arguments);
// post-logic
return retVal;
};
}
Now I want to wrap ALL of the functions in my application, i.e.
All the recursive public functions of the object
All private scope functions
All anonymous functions
Anything else I might have forgotten.
My purpose in doing this is to implement a "JS Profiler" that will run alongside my application during automated testing, and output performance data to logs.
I need this for testing purposes, so the solution must have minimal changes to the actual code of my application.
Possible solutions I've considered:
Public methods can be easily traversed and replaced using a recursive object traversal function.
Some hack using eval() to be able to access private methods.
Ideally, to handle all cases, I could use a proxy HTTP server (Node.js for example) that will transform each javascript file before sending it to the browser. This way my codebase will remain clean, but my tests will have the necessary changes.
The first 2 are only partial solutions, and the last one seems like an overkill and also a potential "bug factory"...
Does anyone have any other ideas on how to achieve what I need?
Decided to test out Meteor JS today to see if I would be interested in building my next project with it and decided to start out with the Deps library.
To get something up extremely quick to test this feature out, I am using the 500px API to simulate changes. After reading through the docs quickly, I thought I would have a working example of it on my local box.
The function seems to only autorun once which is not how it is suppose to be working based on my initial understanding of this feature in Meteor.
Any advice would be greatly appreciated. Thanks in advance.
if (Meteor.isClient) {
var Api500px = {
dep: new Deps.Dependency,
get: function () {
this.dep.depend();
return Session.get('photos');
},
set: function (res) {
Session.set('photos', res.data.photos);
this.dep.changed();
}
};
Deps.autorun(function () {
Api500px.get();
Meteor.call('fetchPhotos', function (err, res) {
if (!err) Api500px.set(res);
else console.log(err);
});
});
Template.photos.photos = function () {
return Api500px.get();
};
}
if (Meteor.isServer) {
Meteor.methods({
fetchPhotos: function () {
var url = 'https://api.500px.com/v1/photos';
return HTTP.call('GET', url, {
params: {
consumer_key: 'my_consumer_key_here',
feature: 'fresh_today',
image_size: 2,
rpp: 24
}
});
}
});
}
Welcome to Meteor! A couple of things to point out before the actual answer...
Session variables have reactivity built in, so you don't need to use the Deps package to add Deps.Dependency properties when you're using them. This isn't to suggest you shouldn't roll your own reactive objects like this, but if you do so then its get and set functions should return and update a normal javascript property of the object (like value, for example), rather than a Session variable, with the reactivity being provided by the depend and changed methods of the dep property. The alternative would be to just use the Session variables directly and not bother with the Api500px object at all.
It's not clear to me what you're trying to achieve reactively here - apologies if it should be. Are you intending to repeatedly run fetchPhotos in an infinite loop, such that every time a result is returned the function gets called again? If so, it's really not the best way to do things - it would be much better to subscribe to a server publication (using Meteor.subscribe and Meteor.publish), get this publication function to run the API call with whatever the required regularity, and then publish the results to the client. That would dramatically reduce client-server communication with the same net result.
Having said all that, why would it only be running once? The two possible explanations that spring to mind would be that an error is being returned (and thus Api500px.set is never called), or the fact that a Session.set call doesn't actually fire a dependency changed event if the new value is the same as the existing value. However, in the latter case I would still expect your function to run repeatedly as you have your own depend and changed structure surrounding the Session variable, which does not implement that self-limiting logic, so having Api500px.get in the autorun should mean that it reruns when Api500px.set returns even if the Session.set inside it isn't actually doing anything. If it's not the former diagnosis then I'd just log everything in sight and the answer should present itself.
I noticed the following pattern in socket.io-node:
// e.g. 1
socket.volatile.emit('bieber tweet', tweet);
// e.g. 2
socket.broadcast.json.send({ a: 'message' });
more generally, it seems to be of the style:
someObject.functionFlagA.functionFlagB.functionFlagEtc.someFunction(/* etc */);
What is this pattern called, where you add flags which may affect the execution of a function, in a chain of accessors which each return the target function (with any other available/appropriate chainable accessors)? When is it appropriate over, say, just passing some parameters to a function?
Looking at it gave me the idea of creating a sync object for my HTML5 web app like so:
// Saves someObj to localStorage AND to server-maintained session
sync.toLocalStorage.toServer.save(someObj);
...since it would be more self-documenting than:
// Saves someObj to localStorage AND to server-maintained session
sync.save(someObj, true, false, true);
Is this an appropriate use of above pattern?
EDIT 2011-12-06 13:06:15
For the curious, this is how socket.io implements it:
Socket.prototype.__defineGetter__('volatile', function () {
this.flags.volatile = true;
return this;
});
Which is used in chain to ultimately call the following internal function which sends a packet and clears the flags:
Socket.prototype.packet = function (packet) {
/* snip */
this.setFlags(); // clears this.flags
return this;
};
I would call it an example of a fluent interface.
From the Wikipedia article:
In software engineering, a fluent interface (as first coined by Eric
Evans and Martin Fowler) is an implementation of an object oriented
API that aims to provide for more readable code. A fluent interface is
normally implemented by using method chaining to relay the instruction
context of a subsequent call.
Of course in your example you have properties instead of methods. But looking at the socket.io-node code, the 'properties' are programmed as __defineGetter__ so you might as well say they are methods.
With regards to your sync object for HTML5: think about the state of the sync object after calling save. Is it reset to its original state or does it remember the configuration? What happens if you call save twice in a row?
If it's just about readability, you can also have callers pass in the configuration like so:
sync.save(someObj, { toLocalStorage: true, toServer: true });
Perhaps this is a bit of a novice JQuery question but:
proper jquery plugins are written inside a closure
thus only methods defining the plugin interface are accessible from the outside
sometimes (or many times) one may need helper methods that it doesn't make sense to expose as part of plugin interface (for example because they alter internal state).
how do those get unit-tested?
For example, looking at blockUI plugin, how can methods install, remove, reset get unit-tested?
To draw a parallel, in Java I would:
create a BlockUI interface containing public methods only (by definition)
create a BlockUIImpl class implementing the above interface. This class would contain install(), remove(), reset() methods that could be public, or (package) protected
So, I would unit-test the Impl but client programmers would interact with the plugin via BlockUI interface.
The same applies here as with any other language and testing privates: To test private methods, you should exercise them via the public interface. In other words, by calling your public methods, the private methods get tested in the process because the public methods rely on the privates.
Generally private methods are not tested separately from the public interface - the entire point is that they are implementation details, and tests should generally not know too much about the specifics of the implementation.
Code written inside a function in JavaScript, or closure as you called it, is not necessarily isolated from the outside of that function.
It is useful to know that functions have visibility of the scope in which they are defined. Any closure you create carries the scope, and therefore functions, of the code that contains it.
This simple example with a jQuery plugin and an artificial "namespace" might serve to prove this assumption:
// Initialise this only when running tests
my_public_test_namespace = function(){};
jQuery.fn.makeItBlue = function() {
makeItBlue(this);
function makeItBlue(object) {
object.css('color','blue');
}
if(typeof my_public_test_namespace != "undefined") {
my_public_test_namespace.testHarness = function() {
return {
_makeItBluePrivateFn: makeItBlue
}
};
}
};
$("#myElement").makeItBlue(); // make something blue, initialise plugin
console.debug(my_public_test_namespace.testHarness()._makeItBluePrivateFn);
But don't forget you shouldn't really test privates. ;)
I came up with the same question and after navigating and finding answers that not really apply, here's what I ended up to solve a similar problem.
Problem: "I have a widget that has a behavior I want to test to ensure it's working as expected, some of the methods are called internally because they have to solve internal behavior, exposing them as public does not make sense because they wont be called from outside, testing the public methods means you wont test the internals of the widget, so finally what can I do?"
Solution: "Creata a test widget that exposes the methods you are interested in testing and use them in the qunit, here is the example:"
// Namespaces to avoid having conflicts with other things defined similarly
var formeditortest = formeditortest || {};
// widget that inherits from the container I want to test
$.widget( "app.testcontainer", $.app.container, {
executeDrop: function(drop, helper) {
var self = this;
self._executeDrop(drop, helper);
}
});
// Test cases
formeditortest.testDropSimple = function(assert) {
var container = $("<div />");
container.testcontainer();
container.testcontainer("drop", 0, 3);
assert.equal(true, $(innerDiv.children()[0]).hasClass("droparea"));
});
QUnit.test(name, function( assert ) {
formeditortest.testDropSimple(assert);
formeditortest.testDropBottom(assert);
});
Using this method the inherited testcontainer could have the preparation required to test elements and then the qunit will handle the test, this solves my problem, hope this works for someone else that is having troubles to approach these kind of tests.
Critics? welcome to comment, I want to improve this if I'm doing something silly!!!