question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Simplify usage with factory function and internal subscription handling

See original GitHub issue

Hey Shai!

Thanks for this! It makes basic observable testing a lot easier! I replaced almost all marble tests in my current project using observer spies, and I do love them. When you don’t have to make use of the complexity which comes with marble testing, observer spies are a real improvement in terms of clarity and readability. However, I found the few lines to use them still a bit too implementation heavy 😉 I know this is a matter of taste, so please consider this more like a feature proposal than a feature request.

Is your feature request related to a problem? Please describe. Letting test authors handle subscriptions on their own leads to a bit too much boilerplate code.

Describe the solution you’d like I ended up using observer spies like this:

const fakeObservable = of('first', 'second', 'third');
const spy = spyOnObservable(fakeObservable);

// if the observable under test will not complete
// or we just want the spy to stop listening
// this will internally unsubscribe
spy.stop();

// simplified shorthand usage
expect(spyOnObservable(fakeObservable).getFirstValue()).toBe('first');

For that to work, I extended the ObserverSpy Class to handle the subscription itself and added a stop method to give test authors the possibility to clear subscriptions:

class StoppableObserverSpy<T> extends ObserverSpy<T> {
  private observationStopped = new AsyncSubject<never>();

  constructor(observableUnderTest: Observable<T>) {
    super();
    observableUnderTest
      .pipe(
        finalize(() => this.stop()),
        takeUntil(this.observationStopped)
      )
      .subscribe(this);
  }

  public stop(): void {
    if (!this.observationStopped.isStopped) {
      this.observationStopped.complete();
      this.observationStopped.unsubscribe();
    }
  }
}

Additionally I use this simple factory function:

function spyOnObservable<T>(observableUnderTest: Observable<T>) {
  return new StoppableObserverSpy<T>(observableUnderTest);
}

Describe alternatives you’ve considered Maybe the usage of observer spies could be simplified even more by creating custom jasmine/jest matchers, but I have no experience there.

Additional context I guess the proposed modifications could be applied to this library without introducing breaking changes. If you think that these changes would be useful, I’d love to create a PR for discussing implementation details.

Cheers, kat

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:2
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

3reactions
katharinakoalcommented, Jun 16, 2020

Sure thing! I get on to it. 😊

1reaction
shairezcommented, Jun 16, 2020

Thanks a lot @katharinakoal !

@edbzn I agree, having specific matchers means we need to support different frameworks, so it’s better to minimize the peer dependencies.

This could be an extension if it will be useful.

Thanks for the feedback!

Read more comments on GitHub >

github_iconTop Results From Across the Web

The Factory Method Pattern and Its Implementation in Python
The new design of Factory Method allows the application to introduce new features by adding new classes, as opposed to changing existing ones....
Read more >
Why should I use a factory class instead of direct object ...
Factory classes are often implemented because they allow the project to follow the SOLID principles more closely. In particular, the interface segregation ...
Read more >
Dependency Injection vs Factory Pattern - Stack Overflow
Factory pattern is just one way to separate the responsibility of creating objects of other classes to another entity. Factory pattern can be...
Read more >
Design Patterns In Java: Singleton, Factory And Builder
We obtain the object of the singleton class using the getInstance () method and then we can use it as usual to access...
Read more >
Where factory pattern is used in JavaScript?
Simply put, a factory is just a function, that returns an object. So, let's re-implement the exact same behavior using a factory function....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found