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)