Skip to content

Commit

Permalink
adding spyOnConstructor
Browse files Browse the repository at this point in the history
  • Loading branch information
searls committed May 8, 2012
1 parent 86baf18 commit bd889e9
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 3 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,31 @@ someSpy("correct","params");
expect(window.globalsRock).toBe(true);
```

# Spying on constructors

jasmine-stealth adds a facility to spy on a constructor. That way, when your subject code
that's under test instantiates a collaborator, you can access its methods as a collection of spies.

Say we have a `view` that instantiates a `model`. Here's an example spec that uses `spyOnConstructor` to isolate the view from the model.

``` coffee
#source
class window.View
serialize: ->
model: new Model().toJSON()
class window.Model

#specs
describe "View", ->
describe "#serialize", ->
Given -> @modelSpies = spyOnConstructor(window, "Model", "toJSON")
Given -> @subject = new window.View()
Given -> @modelSpies.toJSON.andReturn("some json")
When -> @result = @subject.serialize()
Then -> expect(@result).toEqual
model: "some json"
```

# Custom matchers

The problem:
Expand Down
38 changes: 38 additions & 0 deletions spec/jasmine-stealth-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,44 @@ describe "jasmine-stealth", ->
expect(save).toHaveBeenCalledWith(captor.capture())
expect(captor.value.name).toBe("foo")

describe "window.spyOnConstructor", ->
describe "a simple class", ->
class window.Pizza
makeSlice: -> "nah"

context "spying on the constructor - string method arg", ->
Given -> @pizzaSpies = spyOnConstructor(window, "Pizza", "makeSlice")
When -> new Pizza("banz").makeSlice("lol")
Then -> expect(@pizzaSpies.constructor).toHaveBeenCalledWith("banz")
Then -> expect(@pizzaSpies.makeSlice).toHaveBeenCalledWith("lol")

context "spying on the constructor - array method arg", ->
Given -> @pizzaSpies = spyOnConstructor(window, "Pizza", ["makeSlice"])
When -> new Pizza("banz").makeSlice("lol")
Then -> expect(@pizzaSpies.constructor).toHaveBeenCalledWith("banz")
Then -> expect(@pizzaSpies.makeSlice).toHaveBeenCalledWith("lol")

context "normal operation", ->
Given -> @pizza = new Pizza
Then -> @pizza.makeSlice() == "nah"

describe "a collaboration", ->
class window.View
serialize: ->
model: new Model().toJSON()
class window.Model

context "stubbing the model's method", ->
Given -> @modelSpies = spyOnConstructor(window, "Model", "toJSON")
Given -> @subject = new window.View()
Given -> @modelSpies.toJSON.andReturn("some json")
When -> @result = @subject.serialize()
Then -> expect(@result).toEqual
model: "some json"







37 changes: 34 additions & 3 deletions src/jasmine-stealth.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,40 @@ root = this

#private helpers

isFunction = (thing) ->
Object::toString.call(thing) is "[object Function]"
_ = (obj) ->
each: (iterator) ->
iterator(item) for item in obj
isFunction: ->
Object::toString.call(obj) is "[object Function]"
isString: ->
Object::toString.call(obj) is "[object String]"

#spyOnConstructor

root.spyOnConstructor = (owner, classToFake, methodsToSpy = []) ->
methodsToSpy = [methodsToSpy] if _(methodsToSpy).isString()

spies = constructor: jasmine.createSpy("#{classToFake}'s constructor")
fakeClass = class
constructor: -> spies.constructor.apply(@, arguments)

_(methodsToSpy).each (methodName) ->
spies[methodName] = jasmine.createSpy("#{classToFake}##{methodName}")
fakeClass.prototype[methodName] = -> spies[methodName].apply(@,arguments)

fake(owner, classToFake, fakeClass)
spies

unfakes = []
afterEach ->
_(unfakes).each (u) -> u()
unfakes = []

fake = (owner, thingToFake, newThing) ->
originalThing = owner[thingToFake]
owner[thingToFake] = newThing
unfakes.push ->
owner[thingToFake] = originalThing

#stub nomenclature

Expand All @@ -23,7 +54,7 @@ jasmine.createStubObj = (baseName, stubbings) ->
for name of stubbings
stubbing = stubbings[name]
obj[name] = jasmine.createSpy(baseName + "." + name)
if isFunction(stubbing)
if _(stubbing).isFunction()
obj[name].andCallFake stubbing
else
obj[name].andReturn stubbing
Expand Down

0 comments on commit bd889e9

Please sign in to comment.