testingdata-bindingblazorbunit

bUnit not updating bound property


I wrote a Blazor Client component which I'm trying to test using a bUnit .razor test.

The component contains a text input that is bound to a MyValue property. The input listens to @onkeyup event and adds the MyValue value to a List when Enter key is pressed.

The input element looks like this: <input type="text" @bind-value="MyValue" @bind-value:event="onchange" @onkeyup="InputOnKeyUp"/>

The InputOnKeyUp handler looks like this:

private void InputOnKeyUp(KeyboardEventArgs e)
{
    if (e.Code == "Enter" || e.Code == "NumpadEnter")
    {
        var trimmed = MyValue.Trim();

        if (!model.MyList.Contains(trimmed) && !string.IsNullOrEmpty(trimmed))
            model.MyList.Add(trimmed);

        MyValue = "";
    }
}

I am accessing the input element in the bUnit test with .Find function, like so: var textBox = cut.Find("input");

When passing keys from bUnit, the MyValue property, which the input is bound to, doesn't get updated, even though the application works as expected. I am passing the keys like so:

var textBox = cut.Find("input");
textBox.KeyUp("v");
textBox.KeyUp("a");
textBox.KeyUp("l");
textBox.KeyUp(Key.Space);
textBox.KeyUp("1");

I saw here that I should use the change event, but I need access to the key that is pressed, so I can't go that way.

[EDIT] I'm including the entire test file:

@code {
    public void HappyPath()
    {
        using var ctx = new TestContext();
        ctx.Services.AddScoped<IJsApiService, JsApiService>();

        var values = new List<string>();

        var cut = ctx.Render(@<MyComponent MyValues="values"/>);

        cut.Find(".mud-chip-content").TextContent.Should().Be("val 1");
        
        var textBox = cut.Find("input");

        textBox.KeyUp("v");
        textBox.KeyUp("a");
        textBox.KeyUp("l");
        textBox.KeyUp(Key.Space);
        textBox.KeyUp("2");

        textBox.KeyUp(Key.Enter);

        var chips = cut.FindAll(".mud-chip-content");
        chips.Count.Should().Be(2);
        chips.Last().TextContent.Should().Be("val 2");

        values.Count.Should().Be(2);
        values.Last().Should().Be("val 2");

        cut.Find(".mud-chip-close-button").Click();

        chips.Count.Should().Be(1);
        cut.Find(".mud-chip-content").TextContent.Should().Be("val 2");

        values.Count.Should().Be(1);
        values.First().Should().Be("val 2");
    }
}

Any solutions?


Solution

  • The KeyUp method of bUnit will just invoke your onkeyup event that is attached to your input element. It will not enter the characters one-by-one like an end-to-end testing framework like playwright.

    Therefore you have to go with the approach, as you already mentioned, of using Change:

    // Arrange
    var textBox = cut.Find("input");
    textBox.Change("val 1");
    
    // Act
    textBox.KeyUp(Key.Enter);
    
    // Assert
    AssertMyValueIsInModel();
    

    At least from the code you provided your onkeyup doesn't have any other side-effects. So the given code will put the "val 1" into the input box that is bound to MyValue and when we raise the onkeyup event, we'll add the value to the model's list.