title: How test listener on my custom event emitter in node typescript
body: <p>I'm trying to test a service that has a listener of the a custom Event Emitter in node with typescript and mocha, sinon.</p>
  <p>My custom emmiter;</p>
  <pre><code>class PublishEmitter extends EventEmitter {
    publish(id: string) {
      this.emit('publish', id);
    }
  }
  </code></pre>
  <p>My service use case:</p>
  <pre><code>export default class PublishVehicle {
    constructor(
      private findVehicle: FindVehicle, // Service that contains find methods on repository
      private updateVehicle: UpdateVehicle, // Service that contains update methods on repository 
      private logger: ILogger,
    ) {
      this.producer = producer;
      this.logger = logger;
    }
  
    listen() {
      this.logger.log('debug', 'Creating listener on PublishEmitter');
      this.publishListener = this.publishListener.bind(this);
      pubsub.on('publish', this.publishListener);
    }
  
    /**
     * Listener on PublishEmitter.
     *
     * @param event
     */
    async publishListener(event: string) {
      try {
        const vehicle = await this.findVehicle.findById(event);
  
        if (vehicle?.state === State.PENDING_PUBLISH) {
          // 
          const input = { state: State.PUBLISH };
          await this.updateVehicle.update(vehicle.id, input);
          this.logger.log('debug', `Message sent at ${Date.now() - now} ms`);
        }
        this.logger.log('debug', `End Vehicle's Publish Event: ${event}`);
      } catch (error) {
        this.logger.log('error', {
          message: `publishListener: ${event}`,
          stackTrace: error,
        });
      }
    }
  }
  </code></pre>
  <p>and in my test file:</p>
  <pre><code>import chai from 'chai';
  const { expect } = chai;
  
  import sinon from 'sinon';
  import { StubbedInstance, stubInterface } from 'ts-sinon';
  import pubsub from './PublishEmitter';    
  
  
  describe('Use Case - Publish Vehicle', function () {
    let mockRepository: MockVehicleRepository;
    let publishVehicle: PublishVehicle;
    let findVehicleUseCase: FindVehicle;
    let updateVehicleUseCase: UpdateVehicle;
  
    before(() =&gt; {
      const logger = Logger.getInstance();
      mockRepository = new MockVehicleRepository();
      findVehicleUseCase = new FindVehicle(mockRepository, logger);
      updateVehicleUseCase = new UpdateVehicle(mockRepository);
  
      publishVehicle = new PublishVehicle(
        findVehicleUseCase,
        updateVehicleUseCase,      
        logger,
      );
    });
  
    afterEach(() =&gt; {
      // Restore the default sandbox here
      sinon.restore();
    });
  
    it('Should emit event to publish vehicle', async () =&gt; {
  
      const vehicle = { ... }; // dummy data
  
      const stubFindById = sinon
        .stub(mockRepository, 'findById')
        .returns(Promise.resolve(vehicle));
  
      const stubUpdate = sinon
        .stub(mockRepository, 'update')
        .returns(Promise.resolve(vehicle));    
  
      const spy = sinon.spy(publishVehicle, 'publishListener');
  
      publishVehicle.listen();
      pubsub.publish(vehicle.id);
  
      expect(spy.calledOnce).to.be.true; // OK
      expect(stubFindById.calledOnce).to.be.true; // Error (0 call)
      expect(stubUpdate.calledOnce).to.be.true; // Error (0 call)
    });
  });
  </code></pre>
  <p>When I debug this test, indeed the methods are called but they seem to be executed after it has gone through the last expect lines.</p>
  <p>The output:</p>
  <pre><code>1 failing
  
  1) Use Case - Publish Vehicle
     Should emit event to publish vehicle:
  
    AssertionError: expected false to be true
    + expected - actual
  
    -false
    +true
  </code></pre>
  <p><strong>UPDATE</strong></p>
  <p>Finally I was be able to solve my problem wrapping expect lines in setTimeout.</p>
  <pre><code>setTimeout(() =&gt; {
      expect(spy.calledOnce).to.be.true; // OK
      expect(stubFindById.calledOnce).to.be.true; // OK
      expect(stubUpdate.calledOnce).to.be.true; // OK
    done();
  }, 0);
  </code></pre>