Jasmine/JavaScript: Test that a new object was created

时间:2017-04-10 00:03:20

标签: javascript jasmine

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>

3 个答案:

答案 0 :(得分:1)

经过大量的试验和错误(以及搜索)后,我无法覆盖对new Bassist()的调用并将其替换为间谍对象。相反,我在Band类中创建了一个单独的方法来处理Bassist对象创建,然后在它上面插入一个间谍。

谁知道这是不错的做法,但它对我有用。

&#13;
&#13;
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()
    })
  })
})
&#13;
<!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>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

This is because band.start is not actually calling Bassist.prototype.constructor (which should be replaced by the spy), but rather is calling Bassist (which is not the spy).

The only way you could make it spy on Bassist would be to actually replace Bassist on that lexical scope.

答案 2 :(得分:0)

为了检查构造函数是否被调用,您可以检查instanceof运算符

的结果

&#13;
&#13;
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', () => {
      let band = new Band('The Foobars')
      band.start()
      expect(band.bassist instanceof Bassist).toBeTruthy()
    })
  })
})
&#13;
<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>
&#13;
&#13;
&#13;

有助于解决测试问题,可以是dependency injection模式。考虑一下Bassist构造函数调用一些allSortOfOtherCode方法。你可以窥探它并确认它已被执行。

&#13;
&#13;
class Bassist {
  constructor() {
    console.log('bassist joined')
    this.allSortOfOtherCode()
  }

  allSortOfOtherCode() {

  }
}

class Drummer {
  constructor() {
    console.log('drummer joined')
  }
}

class Band {
  constructor(name, bassist, drummer) {
    this.name = name
    this.bassist = bassist
    this.drummer = drummer
  }

  start() {
    this.bassist = new this.bassist()
    this.drummer = new this.drummer()
  }
}

describe('Band', () => {
  describe('start()', () => {
    it('creates a new bassist', () => {
      let band = new Band('The Foobars', Bassist, Drummer)
      expect(band.bassist instanceof Bassist).toBeFalsy()
      band.start()
      expect(band.bassist instanceof Bassist).toBeTruthy()
    })

    it('creates bassist from passed object', () => {
      let bassist = jasmine.createSpy('bassist')
      let band = new Band('The Foobars', bassist, Drummer)
      expect(bassist).not.toHaveBeenCalled()
      band.start()
      expect(bassist).toHaveBeenCalled()
    })

    it('calls `allSortOfOtherStuff()`', function() {
      spyOn(Bassist.prototype, 'allSortOfOtherCode')
      let band = new Band('The Foobars', Bassist, Drummer)
      band.start()
      expect(Bassist.prototype.allSortOfOtherCode).toHaveBeenCalled()
    })
  })
})
&#13;
<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>
&#13;
&#13;
&#13;