Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(better) support for RXJS subscriptions #226

Closed
Martinspire opened this issue Nov 5, 2020 · 10 comments · Fixed by #227 or #245
Closed

(better) support for RXJS subscriptions #226

Martinspire opened this issue Nov 5, 2020 · 10 comments · Fixed by #227 or #245
Assignees
Labels

Comments

@Martinspire
Copy link

Martinspire commented Nov 5, 2020

So when you mock a component or service that contains or has functions that return a subscription, it becomes difficult to easily test that with a mocked component.

Now I get that RXJS isn't a mandatory part of Angular, but seeing how many people use it now, I feel that the types/functions should be supported to mock the response or have a way to inject a value when the mocked component is set up.

Either that or the readme should have more detail on how to easily do this, as there's lots of folks that want to do this. Especially when the ngOnInit triggers a subscription, it requires more code to get some data in your mocked component before your first test, but you'd rather inject the data in your test so you have more control over executing multiple use cases.

I'm not entirely sure how the code should look like, but I feel that right now I can't really use ng-mocks whenever there is a subscription in my service that the oninit of my component that I'm testing, is going to call for.

So when a service has a function that returns a subscription, I'd like ng-mocks to recognize that and initialize the subscription (with an empty value to start with, or some way to provide the initial value), so I can do something with that.

Right now you'd often get a TypeError: Cannot read property 'subscribe' of undefined because the value isn't initialized as a subscription. The cop-out would be to just inject the service and go from there but thats not really black-box testing

@satanTime
Copy link
Member

satanTime commented Nov 5, 2020

Hi @Martinspire,

thanks for the report. Might you provide an example of the code you want to test? Usually you might use MockProvider, .mock or MockInstance for that and provide an observable the code requires.

Unfortunately, return types exist only in typescript code. Therefore in javascript runtime we don't have them, and I don't know a solution to detect them. That's why angular uses decorators, it allows to collect information about constructors for DI.
If you know the solution - please share it and I'll be glad to work on its integration.

It's quite hard, if it is even possible, to predict what should be returned and how it should behave, and looks like, only developers know the right answer.

What I usually do is:

MockBuilder(Component, Module).mock(Service, {prop$: EMPTY});

or in case of more complicated cases

MockInstance(Service, (service, injector) => {
  service.prop$ = of(injector.get(TOKEN));
});

Without ngMocks, code would be almost the same, but with more lines of code.

TestBed.configureTestingModule({
  providers: [{
    provide: Service,
    useValue: {
      prop$: EMPTY
    },
  }],
})

So, still, if we want to mock real code - we have to spend some time to provide a proper stub object.

@satanTime
Copy link
Member

satanTime commented Nov 5, 2020

From your suggestions, I can add a section in readme how to mock observables in constructors and lifecycle hooks.
If it helped. Anyways, it requires developers to specify a mocked copy explicitly.

satanTime referenced this issue in satanTime/ng-mocks Nov 5, 2020
@satanTime
Copy link
Member

satanTime commented Nov 5, 2020

Hi @Martinspire,

might you check whether the section fits your expectations? https://github.com/ike18t/ng-mocks#how-to-fix-typeerror-cannot-read-property-subscribe-of-undefined

satanTime referenced this issue in satanTime/ng-mocks Nov 5, 2020
satanTime referenced this issue in satanTime/ng-mocks Nov 5, 2020
@satanTime
Copy link
Member

satanTime commented Nov 5, 2020

@satanTime satanTime linked a pull request Nov 6, 2020 that will close this issue
@satanTime satanTime self-assigned this Nov 6, 2020
@satanTime satanTime added the enhancement New feature or request label Nov 6, 2020
satanTime added a commit that referenced this issue Nov 7, 2020
## [10.5.3](v10.5.2...v10.5.3) (2020-11-07)

### Bug Fixes

* an example how to handle "TypeError: Cannot read property 'subscribe' of undefined" ([6501a87](6501a87)), closes [#226](#226)
* info how to solve "type is part of the declarations of 2 modules" ([f5ee1bc](f5ee1bc))
* mock-render proxy ([eaeabba](eaeabba))
* relaxed signature of MockInstance ([dccaa2d](dccaa2d))
@satanTime
Copy link
Member

satanTime commented Nov 7, 2020

v10.5.3 has been released and contains a fix for the issue.
Feel free to reopen the issue or to submit a new one if you meet any problems.

@satanTime satanTime reopened this Dec 1, 2020
satanTime referenced this issue in satanTime/ng-mocks Dec 1, 2020
satanTime referenced this issue in satanTime/ng-mocks Dec 1, 2020
satanTime referenced this issue in satanTime/ng-mocks Dec 1, 2020
satanTime referenced this issue in satanTime/ng-mocks Dec 1, 2020
@satanTime
Copy link
Member

satanTime commented Dec 1, 2020

Hi @Martinspire,

I hope this finds you well.

I think I found a way to implement what you described: https://github.com/ike18t/ng-mocks#ngmocksdefaultmock

Might you check if this fits your expectations? ng-mocks.zip

Here you can find examples for tests: https://github.com/ike18t/ng-mocks/tree/master/tests/ng-mocks-default-mock

Looking forward to hearing from you.

satanTime referenced this issue in satanTime/ng-mocks Dec 2, 2020
@satanTime satanTime linked a pull request Dec 2, 2020 that will close this issue
satanTime referenced this issue in satanTime/ng-mocks Dec 3, 2020
@satanTime
Copy link
Member

v11.2.0 has been released and contains a fix for the issue. Feel free to reopen the issue or to submit a new one if you meet any problems.

@Martinspire
Copy link
Author

Sorry for the lack of activity. Just checked a few links and they were not found but I just looked at the 2 releases and it fixes my issue very nicely. Thanks for the help and explanation!

@satanTime
Copy link
Member

satanTime commented Dec 15, 2020

Hi @Martinspire,

glad to see you back :)
I'll fix the links for needs of other users. Thanks for the hint.

Might I ask you to provide a feedback or to drop a few words how ngMocks.defaultMock works for you, whether there are some obstacles you are facing, and if you wanted to improve something?

Thank you in advance!

@Martinspire
Copy link
Author

I've only done work on a few tests lately, but it seems to have fixed my issues and improved a few other things too. I do think I won't always use defaultMock as I still prefer to mock only what I need for my tests, but for some generic functions it seems to provide an easy interface. Thanks for the work and thanks for the feedback. Much appreciated!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants