bUnit-dev / bUnit

bUnit is a testing library for Blazor components that make tests look, feel, and runs like regular unit tests. bUnit makes it easy to render and control a component under test’s life-cycle, pass parameter and inject services into it, trigger event handlers, and verify the rendered markup from the component using a built-in semantic HTML comparer.
https://bunit.dev
MIT License
1.14k stars 105 forks source link

Scoped IComponentActivator breaks bUnit #1138

Closed egil closed 1 year ago

egil commented 1 year ago

I'm pretty sure the problem reported in the SO question below is due to Blazorise registering a IComponentActivator as scoped, replacing our singleton registered BunitComponentActivator. However, since the WebTestRenderer is registered as a singleton it cannot be resolved.

The fix may be to register the renderer as a scoped service and all other dependent services like this too.

https://stackoverflow.com/questions/76597158/bunit-blazorise-cannot-consume-scoped-service-microsoft-aspnetcore-components

related: #1129

linkdotnet commented 1 year ago

I'll quote the official Blazorise docs:

For testing purposes, there is currently an internal Blazorise Service that should be configured as Transient so the bUnit test engine does not throw an error. You should add this setup: ctx.Services.AddBlazorise().Replace(ServiceDescriptor.Transient<IComponentActivator, ComponentActivator>());

Other than that it should pretty much work out of the box. Let us know if you're having any difficulties. For some testing examples, you can look at some of our tests</Blazorise.Link>.

That said, that would help the person in question on SO.

egil commented 1 year ago

Great that they are aware of this in their docs.

I still think it may be worth changing our renderer registration to scoped. AFAICT there are no down sides in that for us and it will make us more compatible.

linkdotnet commented 1 year ago

That is a good point - it goes a bit into the direction of https://github.com/bUnit-dev/bUnit/issues/1018. Or better #1018 is one option how we would solve this issue.

Regarding SO: Do you answer to the OP with the Blazorise docs?

linkdotnet commented 1 year ago

Great that they are aware of this in their docs.

I still think it may be worth changing our renderer registration to scoped. AFAICT there are no down sides in that for us and it will make us more compatible.

Well, we would have to change the scope of almost all singleton to scoped to make that work. For example the BunitHtmlParser is a singleton that tries to resolve a scoped service -> Exception.

As this bubbles up until the TestContext we should be aware of changed behavior (or just create a scope from the beginning until the end of TestContext).

egil commented 1 year ago

Correct. My understanding is that a scoped service can depend on a singleton service, so I do not expect this would break users. It would solve a problem like the one being reported here, where users have to take extra steps.

Do you see any downsides to us registering all our services as scoped?

linkdotnet commented 1 year ago

Correct. My understanding is that a scoped service can depend on a singleton service, so I do not expect this would break users. It would solve a problem like the one being reported here, where users have to take extra steps.

Do you see any downsides to us registering all our services as scoped?

Yes, but singleton services can not depend on scoped services. Like the BunitHtmlParser that is a singleton, can not depend on TestRenderer that is a scoped service.

Anyway - making everything scoped would be my preferred anyway. Technically it wouldn't change much the majority of use cases.

egil commented 1 year ago

Im reverting the change where all services are registered as scoped. Any service user that depends on one of the Blazor services we are implementing registered as a singleton will be unable to get to our scoped services.