While writing a unit test for a blazor component which renders a TreeView from Telerik, I stumbled upon this error:
Message:
Test method Redacted.Web.Client.UnitTests.Components.TreeViewTest.PerformSearch_PerformEmptySearch_NoSearchPerformed threw exception:
System.InvalidOperationException: The render handle is not yet assigned.
Stack Trace:
RenderHandle.ThrowNotInitialized()
RenderHandle.Render(RenderFragment renderFragment)
ComponentBase.StateHasChanged()
TreeView.PerformSearch(String searchQuery) line 78
TreeView.PerformSearch() line 60
TreeViewTest.PerformSearch_PerformEmptySearch_NoSearchPerformed() line 42
ThreadOperations.ExecuteWithAbortSafety(Action action)
^ Tldr: It crashes when it runs StateHasChanged. I assume it because the ComponentBase has not been initialized when it is run as a unit test.
This is currently what my test looks like:
[TestInitialize]
{
_treeView = new TreeView()
var onUpdateMock = new Mock<Action>();
_treeView.OnUpdate = onUpdateMock.Object;
}
[TestMethod]
public async Task PerformSearch_PerformEmptySearch_NoSearchPerformed()
{
string searchText = string.Empty;
_treeView.Data = generateTreeViewMockData();
_treeView.PerformSearch(searchText);
Assert.AreEqual(0, _treeView.ExpandedItems.Count());
Assert.AreEqual(generateTreeViewMockData().Count, _treeView.Data.Count);
}
And this is what the function looks like:
public void PerformSearch(string searchQuery)
{
SearchQuery = searchQuery;
ExpandedItems = new List<Object>();
if (string.IsNullOrEmpty(searchQuery))
{
ClearSearchQuery();
}
else
{
var result = FilterData(Data.ToList(), searchQuery);
FilteredData = result.Count == 0 ? FilteredData : result;
}
StateHasChanged();
}
Is there any way to mock the ComponentBase, or is there a built in function for this purpose?
The first thing I tried was removing any unnecessary usage of StateHasChanged() in my code, but this last one, is essential for the functionality of my component.
I also tried simply creating a mock of ComponentBase, to then use mock.Setup(x => x.StateHasChanged()...). That does not work however since the the method is protected.
Notes: I do not have access to any other testing libraries. I am only able to use MSTest and Moq.
You can try to override protected method ShouldRender()
of your component and return false if it's inside unit test (perhaps use global or local flag)
public static bool IsUnitTest = false;
protected override bool ShouldRender()
{
return base.ShouldRender() && !IsUnitTest;
}