Skip to content

Commit e5f6566

Browse files
committed
fix: await task when calling SetDirectParametersAsync
fix: await task when calling SetDirectParametersAsync
1 parent a23fa20 commit e5f6566

4 files changed

Lines changed: 43 additions & 37 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ All notable changes to **bUnit** will be documented in this file. The project ad
66

77
## [Unreleased]
88

9+
### Fixed
10+
11+
- If the renderer was not idle when calling `SetParametersAndRender`, the method could return before the parameters were set and the component under test had finished rendering. This was a regression that happened in v1.21.9. Reported by [@Skintkingle](https://github.com/Skintkingle]) in <https://github.com/bUnit-dev/bUnit/issues/1188>. Fixed by [@egil](https://github.com/egil).
12+
913
### Added
1014

1115
- `net8.0` support

src/bunit.core/Extensions/RenderedComponentRenderExtensions.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,15 @@ public static void SetParametersAndRender<TComponent>(this IRenderedComponentBas
3030
throw new ArgumentNullException(nameof(renderedComponent));
3131

3232
var renderer = renderedComponent.Services.GetRequiredService<TestRenderer>();
33-
renderer.SetDirectParameters(renderedComponent, parameters);
33+
34+
try
35+
{
36+
renderer.SetDirectParametersAsync(renderedComponent, parameters).GetAwaiter().GetResult();
37+
}
38+
catch (AggregateException e) when (e.InnerExceptions.Count == 1)
39+
{
40+
ExceptionDispatchInfo.Capture(e.InnerExceptions[0]).Throw();
41+
}
3442
}
3543

3644
/// <summary>

src/bunit.core/Rendering/TestRenderer.cs

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ public void DisposeComponents()
194194
AssertNoUnhandledExceptions();
195195
}
196196
}
197-
197+
198198
#if NET8_0_OR_GREATER
199199
/// <inheritdoc/>
200200
protected override IComponent ResolveComponentForRenderMode(Type componentType, int? parentComponentId,
@@ -207,52 +207,46 @@ protected override IComponent ResolveComponentForRenderMode(Type componentType,
207207
#endif
208208

209209
/// <inheritdoc/>
210-
internal void SetDirectParameters(IRenderedFragmentBase renderedComponent, ParameterView parameters)
210+
internal Task SetDirectParametersAsync(IRenderedFragmentBase renderedComponent, ParameterView parameters)
211211
{
212212
if (disposed)
213213
throw new ObjectDisposedException(nameof(TestRenderer));
214214

215-
// Calling SetDirectParameters updates the render tree
216-
// if the event contains associated data.
217-
lock (renderTreeUpdateLock)
215+
var result = Dispatcher.InvokeAsync(() =>
218216
{
219-
if (disposed)
220-
throw new ObjectDisposedException(nameof(TestRenderer));
221-
222-
var result = Dispatcher.InvokeAsync(() =>
217+
try
223218
{
224-
try
225-
{
226-
IsBatchInProgress = true;
227-
219+
IsBatchInProgress = true;
220+
228221
#if NET8_0_OR_GREATER
229-
var setDirectParametersMethod = typeof(ComponentState).GetMethod("SetDirectParameters", BindingFlags.NonPublic | BindingFlags.Instance)!;
230-
var componentState = GetComponentState(renderedComponent.ComponentId);
222+
var setDirectParametersMethod = typeof(ComponentState).GetMethod("SetDirectParameters", BindingFlags.NonPublic | BindingFlags.Instance)!;
223+
var componentState = GetComponentState(renderedComponent.ComponentId);
231224
#else
232-
var componentState = GetRequiredComponentStateMethod.Invoke(this, new object[] { renderedComponent.ComponentId })!;
233-
var setDirectParametersMethod = componentState.GetType().GetMethod("SetDirectParameters", BindingFlags.Public | BindingFlags.Instance)!;
225+
var componentState = GetRequiredComponentStateMethod.Invoke(this, new object[] { renderedComponent.ComponentId })!;
226+
var setDirectParametersMethod = componentState.GetType().GetMethod("SetDirectParameters", BindingFlags.Public | BindingFlags.Instance)!;
234227
#endif
235-
setDirectParametersMethod.Invoke(componentState, new object[] { parameters });
236-
}
237-
catch (TargetInvocationException ex) when (ex.InnerException is not null)
238-
{
239-
throw ex.InnerException;
240-
}
241-
finally
242-
{
243-
IsBatchInProgress = false;
244-
}
245-
246-
ProcessPendingRender();
247-
});
248-
249-
if (result.IsFaulted && result.Exception is not null)
228+
setDirectParametersMethod.Invoke(componentState, new object[] { parameters });
229+
}
230+
catch (TargetInvocationException ex) when (ex.InnerException is not null)
250231
{
251-
HandleException(result.Exception);
232+
throw ex.InnerException;
233+
}
234+
finally
235+
{
236+
IsBatchInProgress = false;
252237
}
253238

254-
AssertNoUnhandledExceptions();
239+
ProcessPendingRender();
240+
});
241+
242+
if (result.IsFaulted && result.Exception is not null)
243+
{
244+
HandleException(result.Exception);
255245
}
246+
247+
AssertNoUnhandledExceptions();
248+
249+
return result;
256250
}
257251

258252
/// <inheritdoc/>

tests/bunit.core.tests/Rendering/TestRendererTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ public void Test208()
488488
cut.Instance.AfterRenderCount.ShouldBe(2);
489489
cut.Instance.AfterRenderAsyncCount.ShouldBe(2);
490490
}
491-
491+
492492
#if NET8_0_OR_GREATER
493493
[Fact(DisplayName = "Can render components that have a RenderMode attribute")]
494494
public void Test209()
@@ -632,7 +632,7 @@ protected override async Task OnAfterRenderAsync(bool firstRender)
632632
throw new InvalidOperationException();
633633
}
634634
}
635-
635+
636636
#if NET8_0_OR_GREATER
637637
[RenderModeServer]
638638
private sealed class RenderModeServerComponent : ComponentBase

0 commit comments

Comments
 (0)