I'm implementing some testing with Jasmine in my web app. I'm using Coffeescript to write my models, services and view models.
class MyViewModel
constructor: ( @options ) ->
@alert = new Alert
elementId: 'my-alert-element-id'
@service = new MyService
alertId: @alert.elementId
Now I write a test in jasmine
describe 'MyViewModel', ->
sut = null
beforeEach ->
sut = new MyViewModel()
afterEach ->
sut = null
describe 'constructor()', ->
it 'creates a new instance of the ViewModel', ->
expect( sut ).not.toBeNull()
So the problem here is that I've got dependencies on alert and service in my viewModel. This is making the tests annoying to write and maintain.
Are there libraries out there for depency injection in Javascript. I've used several .net libraries like castle windsor and ninject.
Or should I just be adopting a certain type pattern. I should say that I'm using knockout and when I'm using the viewmodel in my actual application it looks something like this.
<script type="text/javascript">
$(function () {
var viewModel = new MyViewModel();
ko.applyBindings(viewModel);
});
</script>
Instead of me creating my own object I'd be asking the injection framework for an instance of MyViewModel I assume.
I'm looking for advice on what pattern or library to adopt to make my testing a bit easier and help decoupling my javascript classes from each other.
Libs I've found:
- Wire - Only ECMA 5+ and I need to support older browsers
- Dijon - Looks ok but I haven't tried it yet.
EDIT: What I ended up doing
- I adopted RequireJs and moved all my objects into AMD style modules
- I use Jamine to run the tests
- I use Sinon to create mocks and stubs
- I use Squire to inject mocks and stubs into my system under test
See coffeescript example of a test file
define ['squire', 'sinon' ], ( squire, sinon ) ->
describe '==== a view model ====', ->
sut = null
testContext = null
beforeEach ->
testContext =
squireInjector: new squire
stubService: sinon.stub()
stubJquery: sinon.stub()
someCallbackSpy: sinon.spy()
testContext.squireInjector.mock(
'jquery', squire.Helpers.returns( stubJquery ) )
testContext.squireInjector.require ['aViewModel'], ( viewModel ) =>
sut = new viewModel
service: testContext.stubService
someCallback: testContext.someCallbackSpy
waitsFor( -> sut? )
afterEach ->
sut = null
testContext = null
describe 'the constructor method should', ->
it 'create a new instance of the view
model and have required dependencies', ->
expect( sut ).toBeDefined
expect( sut.service ).toBeDefined
expect( sut.someCallback ).toBeDefined
describe 'the next method should', ->
it 'increment the route id by one', ->
# Arrange
sut.routeId = 5
# Act
sut.next()
# Assert
expect( sut.routeId ).toEqual( 6 )
expect( testContext.someCallbackSpy.called ).toBe(true)