My goal it to assert that new Bassist()
was called by the start()
method and create a mock object, instead.
This the second test is currently failing with the error "Expected spy constructor to have been called."
class Bassist {
constructor() {
console.log('bassist joined')
}
}
class Drummer {
constructor() {
console.log('drummer joined')
}
}
class Band {
constructor(name) {
this.name = name
this.bassist = null
this.drummer = null
}
start() {
this.bassist = new Bassist()
this.drummer = new Drummer()
}
}
describe('Band', () => {
describe('start()', () => {
it('sets the bassist property', () => {
let band = new Band('The Foobars')
band.start()
expect(band.bassist).not.toBeNull()
})
it('creates a new bassist', () => {
spy = spyOn(Bassist.prototype, 'constructor')
band = new Band('The Foobars')
band.start()
expect(spy).toHaveBeenCalled()
console.log('expect was called')
})
})
})
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Jasmine Specs</title>
<!-- Jasmine v2.5.2 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/jasmine.css"></link>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/jasmine.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/jasmine-html.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/boot.js"></script>
</head>
<body>
</body>
</html>
After a lot of trial and error (and searching), I wasn't able to override the call to new Bassist()
and replace it with a spy object. Instead, I created a separate method within the Band class to handle Bassist object creation, and then put a spy on it.
Who knows if this is good practice, but it works for me.
class Bassist {
constructor() {
console.log('bassist joined')
}
}
class Band {
constructor(name) {
this.name = name
this.bassist = null
}
start() {
this.bassist = this.createBassist()
}
createBassist() {
return new Bassist()
}
}
describe('Band', () => {
let band, createBassistSpy, bassistSpy
beforeEach(() => {
// setup spies
bassistSpy = jasmine.createSpyObj('bassist', ['shred', 'quit', 'otherSickMethod'])
createBassistSpy = spyOn(Band.prototype, 'createBassist')
.and.returnValue(bassistSpy)
// init subject being tested
band = new Band('The Foobars')
})
describe('new', () => {
it('initializes bassist to null', () => {
expect(band.bassist).toBe(null)
})
})
describe('start()', () => {
it('calls the createBassist() method', () => {
band.start()
expect(createBassistSpy).toHaveBeenCalled()
// Not a great test, but ensures we are working with the
// bassistSpy object, and not something else.
expect(band.bassist).toEqual(bassistSpy)
})
it('sets the bassist property', () => {
band.start()
expect(band.bassist).not.toBeNull()
})
})
})
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Jasmine Specs</title>
<!-- Jasmine v2.5.2 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/jasmine.css"></link>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/jasmine.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/jasmine-html.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.5.2/boot.js"></script>
</head>
<body>
</body>
</html>