-1

I would like a test to expect a Thrown Error in case a class property this.url is not defined.

What am I doing wrong here ?

  it('should throw an error if url is not provided by default', async () => {
    // Given
    const Service = require('./services/websocket')

    // When
    const Websocket = new Service()

    // Then
    expect(Websocket.url).toBeUndefined()
    expect(Websocket).toThrowError('Websocket URL is not provided')
  })
// services/websocket.js

class Websocket {
  constructor () {
    this.url = undefined

    if (!this.url) {
      throw new TypeError('Websocket URL is not provided')
    }
  }
}

module.exports = Websocket

Jest error message:

 FAIL  terminal.test.js
  Websocket service provider
    ✕ should throw an error if url is not provided by default (2 ms)

  ● Websocket service provider › should throw an error if url is not provided by default

    TypeError: Websocket URL is not provided

      4 |
      5 |     if (!this.url) {
    > 6 |       throw new TypeError('Websocket URL is not provided')
        |             ^
      7 |     }
      8 |   }
      9 | }

      at new Websocket (services/websocket.js:6:13)
      at Object.<anonymous> (terminal.test.js:7:23)
aspirinemaga
  • 3,753
  • 10
  • 52
  • 95
  • Does this answer your question? [How to test the type of a thrown exception in Jest](https://stackoverflow.com/questions/46042613/how-to-test-the-type-of-a-thrown-exception-in-jest) – Neeraj Kumar Nov 15 '22 at 09:00
  • Well, the websocket object itself is not throwing an error, but the call to `new Service()` is. This error itself is not handled by your test. Nevertheless it's a little bit strange that your class is named `Service` and not `Websocket` as seen in the class definition. – Fabian Strathaus Nov 15 '22 at 09:00
  • Oh, nevermind. I just saw your export. This answers my confusion. – Fabian Strathaus Nov 15 '22 at 09:02
  • @aspirinemaga you tried try-catch block to catch error and then did the assertion? – Neeraj Kumar Nov 15 '22 at 09:07
  • @aspirinemaga I mean in the test case function, not in class. – Neeraj Kumar Nov 15 '22 at 09:15
  • 1
    `expect(Websocket).toThrowError('Websocket URL is not provided')` - you expect accessing the variable to throw an error? Even if you did, that access would be done _before_ `expect` got called, in an attempt to resolve the value to pass to it, so couldn't be caught. Look again at the examples in the docs, and think about how JS control flow works: https://jestjs.io/docs/expect#tothrowerror. – jonrsharpe Nov 15 '22 at 10:29

4 Answers4

0

Another way to assert the error in a class which I find it a more proper way:

it('should throw an error if url is not provided by default', () => {
  // Given
  const Service = require('./websocket')
  
  // When
  const Module = () => new Service()

  // When
  expect(Module).toThrowError('Websocket URL is not defined')
})
class Websocket {
  constructor () {
    this.url = process.env.WS_URL

    if (!this.url) {
      throw new Error('Websocket URL is not defined')
    }
  }
}

module.exports = Websocket
aspirinemaga
  • 3,753
  • 10
  • 52
  • 95
0

 it('should throw an error if url is not provided by default', (done) => {
    // Given
    const Service = require('./services/websocket')

    // When
    try {
      const Websocket = new Service()
    } catch(err){
      expect(Websocket.url).toBeUndefined()
      expect(err.message).toBe("Websocket URL is not provided")
      done()
    }
   

   throw new Error('it did not catch url is not provided error')
  })
JHIH-LEI
  • 104
  • 6
-1

I've managed to make it work.


  it('should throw an error if url is not provided by default', () => {
    // Given
    const Service = require('./services/websocket')

    // When
    let Module

    try {
      Module = new Service()
    } catch (error) {
      Module = error
    }

    expect(Module).toBeInstanceOf(Error)
    expect(Module.message).toBe('Websocket URL is not defined')
  })

  it('should pick up a WS url from env file automatically', () => {
    process.env.WS_URL = 'ws://dummyurl'
    const Service = require('./services/websocket')
    const Module = new Service()

    expect(Module.url).toEqual(process.env.WS_URL)
  })
// services/websocket.js

class Websocket {
  constructor () {
    this.url = process.env.WS_URL

    if (!this.url) {
      throw new Error('Websocket URL is not defined')
    }
  }
}

module.exports = Websocket

aspirinemaga
  • 3,753
  • 10
  • 52
  • 95
-1

I think you're probably looking for something more like

it('should throw an error if url is not provided by default', () => {
  const Service = require('./services/websocket')
  expect(new Service()).toThrowError()
})

The want to check for the URL to be undefined is understandable, but I don't believe anything would execute after the error unless you catch and discard it, so the lack of it being set shouldn't be a show stopper.

aspirinemaga
  • 3,753
  • 10
  • 52
  • 95
therealdakotal
  • 244
  • 1
  • 11
  • Could you recommend some different approach of writing those checks in class constructor instead ? I do understand now that an error is occured before the expect class, without trycatch I wouldn't be able to assert it. – aspirinemaga Nov 15 '22 at 14:45
  • 1
    I think your original class implementation is good. Like you _probably_ don't want to have execution continue if you don't have everything you need to be able to build the connection. An alternative might be to delay the check. For instance, you could delay the check until right before you make the connection. So you would add a `connect` method to your Websocket class and call that in the caller's scope. Your constructor then only assigns the information it's given if it's given it. Then in the connect method, right before you make the ws conn, verify and throw there. – therealdakotal Nov 15 '22 at 20:29
  • ``` class Websocket { constructor () { this.url = process.env.WS_URL } connect() { if (!this.url) { throw new Error('Websocket URL is not defined') } } } module.exports = Websocket``` ``` //example const service = new Service(); service.connect() // throws since we didn't provide a URL ``` – therealdakotal Nov 15 '22 at 20:30