Archive for August 2009
No tags
Just a random, late night scribble for the boys and girls out there starting fresh with javascript and not understanding the power that you can harness with it. I’ve given this demonstration before, but it’s always fun to post because someone might learn something new.
Anyway, you might be familiar with your usual function definition, let’s say a function that sums 2 numbers:
function sum(a,b){
return a+b;
}
sum(2,5); // returns 7
That’s fine and dandy… but now let’s change this around a bit to better illustrate what a function is:
var pre = function(a,b){
return a+b;
}
sum(2,5); // returns 7
Yep, that’s right… a function is just an object in javascript and the name of it is simply a variable. Now let’s make this a bit more interesting by creating a function that returns a running sum:
function runningSum(start){
var sum = start;
return function(a){
return sum+=a;
}
}
var sum = runningSum(3);
sum(2); // returns 5
sum(10); // returns 15
As you see, you can have a function return another function in javascript, and that function inherits the scope of the function that created it… in fact we could remove the temporary sum variable and get the same results:
function runningSum(start){
return function(a){
return start+=a;
}
}
var sum = runningSum(3);
sum(2); // returns 5
sum(10); // returns 15
now, lets introduce the arguments variable, which gives you access to an array of agu ments passed into the function. A revised sum function:
function sum(){
var sum = 0;
for(var i = 0; i < arguments.length; i++){
sum += arguments[i];
}
return sum;
}
sum(1,2,2,1); // returns six
The arguments object is a pretty damn cool object, if you want to look further, take a gander at the Mozilla documentation. Using the callee attribute of arguments (which returns the function instance itself), we can do something wicked:
var sum = 0;
function add(a){
sum+=a;
return arguments.callee;
}
add(1)(2)(3);
alert(sum); // displays 6
I find this can come in pretty handy when you need an accumulator of some sort... try it, it works!
Also, you can assign the scope of this while using functions, which can be useful if, for example, you want to call a function where this might resolve to the local scope (think ajax callbacks):
function greeting(){
return "Hello " + this.name;
}
var person = {'name':'James'};
greeting.call(person); // returns "Hello James"
I also prefer to avoid polluting the global scope if I want a script that does something procedural when it's included, in that case I just create a function and execute it on the spot:
(function(){
var bleh = 3;
alert(bleh+5); // alerts 8
})();
alert(bleh); // Reference Error: bleh is not defined
Finally, there's a handy map function on arrays. It's available in Mozilla, but not IE (afaik), however it is also available in jquery, so you can give it a try there.
[1,2,3,4,5].map(function(a){return a*a;}); // returns [1,4,9,16,25]
Overall, pretty basic stuff, but a nice refresher if you are unfamiliar.
No tags
30
Dependency Injection is Not Just For Testing!
No comments · Posted by James Carr in /dev/random, Agile Software Development
Something I have heard in the past is the bemoaning about injecting a dependency just for the sole sake of being able to test the use of that dependency, and while reading email today I saw that someone built a “handy utility” for replacing dependencies without having to make a setter or constructor. While they saw this as a great way to bypass code created “just for testing” I disagree on the reason that Test just quite simply are not Tests.
When you are doing Test Driven Design (note that I didn’t say Development) you are not just creating an exhaustive suite of unit tests to test your code and you’re not “testing everything that could break”, if you are you are doing it wrong. Rather, by test driven design you are describing your design… you are describing the API, how it behaves, how it works. Most importantly, you are using your tests as examples of how the system under test works in a given situation and using the examples to drive how your system is designed!
As such, using Inversion of Control or Dependency Injection to provide the dependencies to your System Under Test is in no way, shape or form creating needless test code… I will tell you right now that if you are creating protected setters to inject dependencies you are misunderstanding Dependency Injection and need to re-read up on it a bit. The way I see it you should have a system that is composed of two kinds of objects… objects that have new littered all over to create objects and objects that do things (sometimes with dependencies provided to them). With this being the case, you don’t want objects that do things and have the new keyword all over the place.
I’ve seen a lot of code written that uses multiple constructors, one that takes a dependency and one no-arg constructor that creates the dependencies it needs itself. This is a general example of code that one might complain is playing lip service to the tests around it, but my solution is do away with the no-arg constructor. You’re injecting at the wrong level. Either do one of the following:
- Use a Dependency Injection framework like Guice, Spring, or PicoContainer
- Push the dependency creation to the client
- Organize code into modules, with the module definitions creating and wiring the dependencies
Just my random thoughts on it… with all the confusion of Test Driven Development being focused on Testing, you can see why I’ve been really preferring Behavior Driven Development for the aspects that BDD is often called “TDD Done Right”.
Dependency Injection is about design, which happens to make you design easier to decouple from dependencies and therefore easier to provide Mocks,Stubs,Fakes,or Spies to describe how the system uses those dependencies.
No tags
No tags
21
JUnit4 + Mockito + Hamcrest = BDD Goodness
2 Comments · Posted by James Carr in Uncategorized
Been tinkering with the 1.8 release of Mockito and found an interesting new feature: support for a Behavior Driven Development syntax.
It’s pretty exciting the readable tests you can create with this new subclass. Here’s a quick example I whipped up during my Mockito presentation today:
package org.jamescarr.MockitoDemo.bdd;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.jamescarr.MockitoDemo.stubs.Bar;
import org.jamescarr.MockitoDemo.stubs.Bartender;
import org.jamescarr.MockitoDemo.stubs.Drink;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class BarSpec {
@Mock Bartender bartender;
private Bar bar;
@Before
public void before(){
bar = new Bar(bartender);
}
@Test
public void shouldGiveMeADrinkWhenIWalkIn(){
given(bartender.askForRandomDrink()).willReturn(Drink.MOJITO);
Drink drink = bar.buyDrink();
assertThat(drink, isMojito());
}
private Matcher isMojito() {
return new IsMojito();
}
}
class IsMojito extends BaseMatcher{
public boolean matches(Object item) {
return "BACARDI MOJITO".equals(((Drink)item).getType());
}
public void describeTo(Description description) {
description.appendText("This drink is not a mojito");
}
}
No tags
