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.11k stars 105 forks source link

Document testing components that use native dependencies #511

Open egil opened 2 years ago

egil commented 2 years ago

Document the how native dependencies will work in a bUnit context.


Original issue text:

Components that use native dependencies cannot be rendered with bUnit.

Simple example (lifted from here):

Let’s add a simple native C function to a Blazor WebAssembly app:

  1. Run dotnet workload install wasm-tools
  2. Create a new Blazor WebAssembly project.
  3. Add a Test.c file to the project.
  4. Add a C function in Test.c for computing factorials:
    int fact(int n)
    {
    if (n == 0) return 1;
    return n * fact(n - 1);
    } 
  5. Add a NativeFileReference for Test.c in your project file:
    <ItemGroup>
    <NativeFileReference Include="Test.c" />
    </ItemGroup>
  6. In Pages/Index.razor add a DllImport for the fact function in generated Test library:
    @using System.Runtime.InteropServices
    ...razor
    @code {
    [DllImport("Test")]
    static extern int fact(int n);
    }
  7. Call fact method from your .NET code.
    <p>@fact(3)</p>
  8. Add a xunit project and add bUnit to it
  9. Create a simple test that renders the Index component:
    public class UnitTest1 : TestContext
    {
    [Fact]
    public void Test1()
    {
        var cut = RenderComponent<Index>();
    }
    }
  10. Doing a dotnet test yields the following error message:
    System.DllNotFoundException : Unable to load DLL 'Test' or one of its dependencies: The specified module could not be found. (0x8007007E)

Options 1 - dont support it

For now, I am content with just telling users to wrap their extern calls in an abstract that they inject into the components that needs it, and then mock/fake that during testing.

egil commented 2 years ago

@SteveSandersonMS / @captainsafia: If you can think of a way for bUnit to run native dll's, I'd love to know.

As far as I can tell from the blog post announcing the feature, this is only works with Blazor WASM, and since bUnit works much more like Blazor Server from an runtime point of view, I get that it might not be possible.

SteveSandersonMS commented 2 years ago

It depends entirely on how a package containing the native dependency is authored. If the package author wants to support running in non-wasm scenarios too (e.g., Blazor Server), they can include Windows, macOS, and Linux versions of the native binary in the architecture-specific directories (https://docs.microsoft.com/en-gb/nuget/create-packages/supporting-multiple-target-frameworks#architecture-specific-folders). In that case their package can also work on the OSes they've provided native dependencies for, and could therefore work under bUnit.

None of this happens automatically - it's up to the package author. If they don't provide native binaries for Windows, say, then the bUnit tests couldn't run on Windows.

egil commented 2 years ago

@SteveSandersonMS so if a package author includes a native binary compiled for the OS that the bUnit test is running on, the [DllImport("Test")] and @using System.Runtime.InteropServices bits in users components will just work?

If that is the case, then I do not see anything in particular that bUnit can do to further add support for this, and it will be up to library authors/component developers to make it work.