-
-
Notifications
You must be signed in to change notification settings - Fork 116
Closed
Description
Attempting to write tests for Telerik Scheduler component. It is getting a null reference exception.
Example:
Testing this component:
@namespace HCHB.BlazorComponents
@typeparam TItem
@using Telerik.Blazor.Components
<TelerikRootComponent>
<TelerikScheduler Data="@Data"
@bind-Date="@SchedulerStartDate"
@bind-View="@SchedulerCurrentView"
AllowUpdate="true"
TItem="TItem">
<SchedulerViews>
<SchedulerDayView StartTime="@DayStart" EndTime="@DayEnd" />
<SchedulerWeekView StartTime="@DayStart" EndTime="@DayEnd" SlotDivisions="1" SlotDuration="30" />
<SchedulerMonthView />
</SchedulerViews>
</TelerikScheduler>
</TelerikRootComponent>
using Telerik.Blazor;
using Microsoft.AspNetCore.Components;
using System.Diagnostics.CodeAnalysis;
namespace HCHB.BlazorComponents
{
public partial class Scheduler<TItem>
{
[Parameter, AllowNull]
public IEnumerable<TItem> Data { get; set; }
[Parameter]
public DateTime SchedulerStartDate { get; set; } = new DateTime(2022, 7, 25);
[Parameter]
public SchedulerView SchedulerCurrentView { get; set; } = SchedulerView.Week;
// only the time portion matters
[Parameter]
public DateTime DayStart { get; set; } = new DateTime(2000, 1, 1, 6, 0, 0);
[Parameter]
public DateTime DayEnd { get; set; } = new DateTime(2000, 1, 1, 19, 0, 0);
}
public enum AppointmentStatus
{
Accepted,
Overdue,
Pending
}
public class SchedulerAppointment
{
public Guid Id { get; set; }
public string Title { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public DateTime Start { get; set; }
public DateTime End { get; set; }
public bool IsAllDay { get; set; }
public SchedulerAppointment()
{
Id = Guid.NewGuid();
}
public AppointmentStatus Status { get; set; }
}
}With this test:
[Fact]
public void NewTelerikTest()
{
_ = RenderComponent<Scheduler<List<SchedulerAppointment>>>();
var button = this.RootComponent.Find("button[id=\"window-test-button\"]");
Assert.Contains("Add Content", button.InnerHtml);
}and using this TestContext...
using Bunit;
using HCHB.BlazorComponents.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.JSInterop;
using System;
using Telerik.Blazor.Components;
using Telerik.Blazor.Services;
using Telerik.JustMock;
namespace HCHB.BlazorComponents.Tests.Common
{
/// <summary>
/// TestContext using a CascadingValue of type <see cref="TelerikRootComponent"/>, rather than the actual implementation.
/// </summary>
public class TelerikTestContext : TestContext
{
#nullable enable
private IRenderedComponent<TelerikRootComponent>? rootComponent;
#nullable disable
public IRenderedComponent<TelerikRootComponent> RootComponent
=> rootComponent ?? throw new InvalidOperationException("The RootComponent is not available before a component has been rendered with the TestContext.");
public TelerikTestContext()
{
// mock the JS Interop service, you cannot use the one coming from the context
var jsRuntimeMock = Mock.Create<IJSRuntime>();
// you can also register a real one for actual localization to test that too
var localizerMock = Mock.Create<ITelerikStringLocalizer>();
// make sure JS Interop is available first
Services.AddSingleton(jsRuntimeMock);
// add the Telerik Blazor services like in a regular app
Services.AddUIServices();
Services.AddSingleton(localizerMock);
}
public override IRenderedFragment Render(RenderFragment renderFragment)
{
EnsureRootComponent();
return base.Render(renderFragment);
}
public override IRenderedComponent<TComponent> Render<TComponent>(RenderFragment renderFragment)
{
EnsureRootComponent();
return base.Render<TComponent>(renderFragment);
}
public override IRenderedComponent<TComponent> RenderComponent<TComponent>(params ComponentParameter[] parameters)
{
EnsureRootComponent();
return base.RenderComponent<TComponent>(parameters);
}
public override IRenderedComponent<TComponent> RenderComponent<TComponent>(Action<ComponentParameterCollectionBuilder<TComponent>> parameterBuilder)
{
EnsureRootComponent();
return base.RenderComponent(parameterBuilder);
}
private void EnsureRootComponent()
{
if (rootComponent is not null) return;
// add a Telerik Root Component to hold all Telerik components and other content
rootComponent = (IRenderedComponent<TelerikRootComponent>)Renderer.RenderComponent<TelerikRootComponent>(new ComponentParameterCollection());
// provide the Telerik Root Component to the child components that need it (the Telerik components)
RenderTree.TryAdd<CascadingValue<TelerikRootComponent>>(p =>
{
p.Add(parameters => parameters.IsFixed, true);
p.Add(parameters => parameters.Value, RootComponent.Instance);
});
}
}
}Results in this output:
Message:
System.NullReferenceException : Object reference not set to an instance of an object.
Stack Trace:
ContentTableBase`1.SetSlotMetrics(Dictionary`2 metrics)
ContentTableBase`1.GetSlotMetrics()
ContentTableBase`1.OnAfterRenderAsync(Boolean firstRender)
TestRenderer.AssertNoUnhandledExceptions() line 384
TestRenderer.Render[TResult](RenderFragment renderFragment, Func`2 activator) line 247
TestRenderer.RenderFragment(RenderFragment renderFragment) line 53
TestContextBaseRenderExtensions.RenderInsideRenderTree(TestContextBase testContext, RenderFragment renderFragment) line 43
TestContextBaseRenderExtensions.RenderInsideRenderTree[TComponent](TestContextBase testContext, RenderFragment renderFragment) line 23
TestContext.Render[TComponent](RenderFragment renderFragment) line 66
TestContext.RenderComponent[TComponent](Action`1 parameterBuilder) line 52
Scheduler.Test1() line 34
Expected behavior:
Expect RenderComponent to not throw an exception here. Unless I am missing something. Have looked at it for a few days and tried various things but always same exception.
Version info:
- bUnit version: 1.14.4
- .NET Runtime and Blazor version: net6.0
- Telerik.UI.for.Blazor 4.0.0
- OS type and version:Windows 10 Enterprise
Metadata
Metadata
Assignees
Labels
No labels