At the end of last week I wrote a class to manage sending e-mail from our application. This class (called it EmailProcessingManager) had all the usual suspects:
- Get a list of to, cc, bcc, from and reply to email addresses
- Find a template
- Replace tokens in said template with values from the database
- Send the email(s)
Wound up making a class for each one of these separate duties and wrote tests for each. But to seal it all together, I wanted to write an integration test that would test the whole operation of sending an email. This test would hit the database, pull in the actual HTML template, replace token values, etc. But what about the actual sending of email? I didn't want to go to the trouble of trying to figure out how to hit a pop email inbox and reading in the email...there had to be an easier way!
ObjectFactory.Inject() to the rescue!
The problem I had was that I wanted to use the entire EmailProcessingManager class as it would be used in production, except I didn't want the mail to actually go out. I wanted all the classes' dependencies to be real implementations except for the class that actually spun up the SMTP client class to send the mail. That's when I found the Inject method.
(Using Moq in this example)
<TestFixtureSetUp()>
Public Sub Setup()
_mailSenderMock = New Mock(Of IEmailSender)
_mailSenderMock.Setup(Function(mock) mock.SendEmail(It.IsAny(Of List(Of MailMessage)))) _
.Callback(Sub(messages) _emailsThatWouldHaveBeenSent = messages)
'Inject the mocked object instead of using the production code
StructureMap.ObjectFactory.Inject(Of IEmailSender)(_mailSenderMock.Object)
'Get an instance of the class under test
_emailProcessingManager = StructureMap.ObjectFactory.GetInstance(Of IEmailProcessingManager)()
Dim recipientList = New List(Of String) From {"paco@joescrabshack.com"}
_emailProcessingManager.ProcessEmailRequest(EmailType.Registration, recipientList)
End Sub
<Test()>
Public Sub Can_create_a_request_for_an_authorization_email_and_have_it_sent_to_the_recipient()
_emailsThatWouldHaveBeenSent.First(Function(email) email.To.First().Address = "paco@joescrabshack.com").ShouldNotBeNull()
End Sub
All of the value of an integration test, but none of the pain of dealing with an external dependency. I like it.
Now that I've discovered this, I have other ideas for it's use. One situation that comes to mind is an integration test that saves a complex object graph to the database. Those tests are always hard to clean up after, so instead of saving the object I'll just use a mock to retrieve the passed object and do my asserts. No messy cleanup!
In the case where you want to create a stub that simply passes the input parameter through to it's return value, you can use this syntax in Moq:
mock.Setup(m => m.Method(DateTime.Now)).Returns((DateTime param) => param);
Documenting this here because I use it just often enough to forget.
I have been using Jasmine’s SpyOn method to stub results for
dependencies within methods.
My goal was to override these stubbed methods in nested describe contexts. My
first thought was to redefine the Spy (stub) using the spyOn method. This fails with an obvious error message:
“Error: xyz has already been spied upon…”. What I needed to understand was that the spy object had
already been created in the outer describe block, so I needed to simply re-use it. Instead of trying to re-declare
the spy, just use the same object and use the andReturn() method to redefine the return value of the stubbed
method.
Here is an illustration:
describe("Outer describe", function() {
beforeEach(function() {
//Setup Stuff
spyOn(someObject, 'someMethod').andReturn(3);
});
it("...", function() {
//Test here
});
describe("Inner Describe", function() {
beforeEach(function() {
//Nested setup stuff
//Fails: "Error: someMethod has already been spied upon"
spyOn(someObject, 'someMethod').andReturn(0);
//Passes: The object has already been initialized as a spy, so use the existing spy object and tell it to change the return value.
someObject.someMethod.andReturn(0);
});
it("...", function() {
objectUnderTest.someMethod();
expect($("input#some-element")).toBeDisabled();
});
});
});
The past week has been spent continuing my journey of refactoring massive amounts of javscript that was written baked
into the jQuery ready callback.
Nagging
Questions
While I've been pulling out behavior and encapsulating it into javascript objects, a few
design questions keep popping up. First, when I need to interact with the DOM I struggle with how to make my
object aware of the page elements. I have at least a few options:
* Inject the DOM elements
into the object constructor:
function SomeClass(element1, element2) {
this.element1 = element1;
this.element2 = element2;
}
This solution allows me to not have to worry about adding DOM elements to a
test fixture. In my test I can just pass object literals into the ctor. The tradeoff is that if the
object depends on many elements then the constructor parameter list can get unwieldy.
* Allow
the object constructor to locate the elements:
function SomeClass() {
this.element1 = $("input#Element1");
this.element2 = $("input#Element2");
}
Here I can avoid the big ctor parameter list, but now I have to simulate
some of my DOM elements inside the test. The testing framework
I'm using makes this very easy, but there's something troubling about duplicating the elements here.
* Pass page elements into object instance methods as needed
function SomeClass() {
this.user_took_some_action = function(element1, element2) {
//Do stuff
}
}
This might appear be a happy medium
between the other two solutions, but it also breaks some of the encapsulation I'm trying to achieve. There are
often times where two or more instance methods interact with the same DOM elements.
I?ve been trying
to observe my TDD patterns to see what leads me to the most testable solution, but it seems like every situation is
different. I'm torn on whether or not I care about consistency.
The next question I keep bumping into
is dealing with service location. Do I pass the dependencies into the constructor and/or instance methods, or
just create them inside the instance methods? Coupled with the above discussion, my parameter lists can start
to get muddled with both DOM elements AND dependencies. Not ideal. Ideally I would just create
dependencies as I need them inside my instance methods:
function SomeClass() {
this.user_took_some_action = function(element1, element2) {
var dependency = new Dependency();
dependency.make_me_some_pie();
//other stuff
}
}
Since javascript is a dynamic language I thought it would be a
breeze to stub out the dependency, and it is...but only after I asked the Twitters for some help: http://gist.github.com/639861
This seems like a great way
to go if you don't mind the extra work/code of stubbing using this technique.
It's been a while since I realized that I had a need to test my Javascript code. The team I'm working with
during the day is building a rich internet application using Javascript and JSON web services. Sales running
through our application are in the 10s of thousands each day. If our application displays something
incorrectly, or doesn't respond to a user interaction in the correct way we are on the line for the cost to our
clients.
Like I said, it's been a while since recognizing the need, so what took so long? For some
reason testing Javascript has been a really difficult thing for me to grok. I sat down at my computer
determined to learn probably 4 or 5 times before finally feeling like I had a handle on what I needed to do.
So what was the hangup? 2 big things:
1) Hadn't unlocked the secrets of Javascript's OOP abilities.
2) My Javascript was married to the DOM.
The biggest mind shift that I had to make was thinking like I
think when I'm writing in C# or VB: use OOP to my advantage! This isn't as obvious as it looks partly because
Javascript's object syntax is... different. To understand objects, public methods, private methods, and
properties I found this article to be a huge help.
This shift in thinking was critical to becoming successful at testing Javascript.
Next up is isolating user
interaction behavior from the DOM. I'm new at this, but so far what has served me well is to group page
elements into logical pieces, and encapsulate their behavior. For instance, in our application we have a
"toolbar" that responds to interactions that the user makes on other elements on the page:

Before refactoring to objects, we were writing all of our
user interaction behavior in the $().ready(...) function from JQuery. Organizing
logic like this simply does not scale. You end up losing sight of interactions on elements and it becomes too
easy to miss something. To solve that problem we encapsulated the toolbar in an object:
function SelectionToolbar(saveButton, getCountsButton, saveDefaultsButton,
radiusButton, featheringButton, mapButton, ...) {
this.saveButton = saveButton;
this.getCountsButton = getCountsButton;
...and so on.
It's called from the page like this:
var selectionToolbar = new
SelectionToolbar($("input#SaveQuery"), $("input#GetCounts"), ...etc
A nice side
effect is that I don't have to keep referencing the DOM element name ever again. When I change the ID of the
DOM elements I only have to change it one place in my Javascript.
When events happen on the page that have
an effect on the toolbar, we simply notify the object of the interaction, and the behavior gets applied to the
toolbar elements internally. This is the encapsulation we've been needing!
In this post I've
described how I changed my mindset to get the code in position to be unit tested. Next up I'll walk through
the first test I wrote and more about the framework I chose to support testing.
If you have any beginner
tips to share about getting started with Javascript OOP or testing please leave them in the comments!