unit-testingmockingblazornsubstitutebunit

How do I mock in injected LocalStorageService is a bUnit test?


I'm using bUnit to test a Blazor component, but am getting stuck with trying to mock the following injected dependency in the component...

  [Inject]
  public ILocalStorageService LocalStorage { get; set; } = null!;

My basic code for creating an instance of the component under test is...

TestComponentSender cut = RenderComponent<TestComponentSender>(ps => ps
    .Add(p => p.NotificationHelper, new TestNotificationHelper())
).Instance;

I can't use the Add method as I did with the NotificationHelper parameter, as the local storage property is injected, not a parameter.

I have tried adding the following line before the above...

Services.AddScoped<ILocalStorageService>();

...but that gives an exception when the test is run...

Cannot instantiate implementation type 'Blazored.LocalStorage.ILocalStorageService' for service type 'Blazored.LocalStorage.ILocalStorageService'

I tried referencing the NSubstitute Nuget package, and adding the following line after creating the component...

cut.LocalStorage = Substitute.For<ILocalStorageService>();

...but that gave a different exception...

Cannot provide a value for property 'LocalStorage' on type 'InspiredGiving.Crm.Areas.General.Shared.TestComponentSender'. There is no registered service of type 'Blazored.LocalStorage.ILocalStorageService'.

Anyone able to advise how I mock this injected dependency?

Update Following Egil's answer, I installed the bUnit test package, and did something similar to the code on the GitHub page...

TestComponentSender cut = RenderComponent<TestComponentSender>(ps => ps
  .Add(p => p.NotificationHelper, new TestNotificationHelper())
).Instance;
cut.LocalStorage = this.AddBlazoredLocalStorage();

However this gave an exception...

System.InvalidOperationException: Cannot provide a value for property 'LocalStorage' on type 'InspiredGiving.Crm.Areas.General.Shared.TestComponentSender'. There is no registered service of type 'Blazored.LocalStorage.ILocalStorageService'

I tried using the approach shown by Robert Harvey in his comment...

Services.AddScoped<ILocalStorageService>(_ => this.AddBlazoredLocalStorage());

...but got the same exception.


Solution

  • I suspect you're very close, but made one small mistake.

    Did you add the mock to the services before or after you created the test component? If it was after, then that would explain the exception.

    Try this...

    // Register mock before creating cut
    Services.AddScoped<ILocalStorageService>(_ => this.AddBlazoredLocalStorage());
    // Now we can create the cut
    TestComponentSender cut = RenderComponent<TestComponentSender>(ps => ps
      .Add(p => p.NotificationHelper, new TestNotificationHelper())
    ).Instance;