Skip to content

Commit 14b5116

Browse files
authored
Throw exception if base.OnInitialzed not called (Fixes #82)
1 parent 1b190e9 commit 14b5116

File tree

8 files changed

+116
-8
lines changed

8 files changed

+116
-8
lines changed

Docs/releases.md

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
* Fix for ([#84](https://github.com/mrpmorris/Fluxor/issues/84) -
55
Allow observer to unsubscribe from all subscriptions whilst executing
66
the callback from a previous subscription
7+
* Fix for ([#82](https://github.com/mrpmorris/Fluxor/issues/82)) -
8+
Throw an informative exception when `FluxorComponent` or `FluxorLayout`
9+
has been inherited and the descendant doesn't call `base.OnInitialized()`.
710

811
### New in 3.6
912
* Ensure synchronous effects are executed synchronously ([#76](https://github.com/mrpmorris/fluxor/issues/76)) -

Source/Fluxor.Blazor.Web/Components/FluxorComponent.cs

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ protected virtual void Dispose(bool disposing)
4444
{
4545
if (disposing)
4646
{
47+
if (StateSubscription == null)
48+
throw new NullReferenceException(ErrorMessages.ForgottenToCallBaseOnInitialized);
49+
4750
StateSubscription.Dispose();
4851
ActionSubscriber?.UnsubscribeFromAllActions(this);
4952
}

Source/Fluxor.Blazor.Web/Components/FluxorLayout.cs

+3
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ protected virtual void Dispose(bool disposing)
4444
{
4545
if (disposing)
4646
{
47+
if (StateSubscription == null)
48+
throw new NullReferenceException(ErrorMessages.ForgottenToCallBaseOnInitialized);
49+
4750
StateSubscription.Dispose();
4851
ActionSubscriber?.UnsubscribeFromAllActions(this);
4952
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Fluxor.Blazor.Web
2+
{
3+
internal class ErrorMessages
4+
{
5+
internal const string ForgottenToCallBaseOnInitialized =
6+
"Have you forgotten to call base.OnInitialized() in your component?";
7+
}
8+
}

Tests/Fluxor.Blazor.Web.UnitTests/Components/FluxorComponentTests/DisposeTests.cs

+33-4
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,58 @@
11
using Fluxor.Blazor.Web.UnitTests.SupportFiles;
2+
using System;
23
using Xunit;
34

45
namespace Fluxor.Blazor.Web.UnitTests.Components.FluxorComponentTests
56
{
67
public class DisposeTests
78
{
8-
private readonly FluxorComponentWithStateProperties Subject;
9+
private readonly FluxorComponentWithStateProperties StateSubject;
910
private readonly MockState<int> MockState1;
1011
private readonly MockState<int> MockState2;
1112

1213
[Fact]
1314
public void UnsubscribesFromStateProperties()
1415
{
15-
Subject.ExecuteOnInitialized();
16-
Subject.Dispose();
16+
StateSubject.ExecuteOnInitialized();
17+
StateSubject.Dispose();
1718

1819
Assert.Equal(1, MockState1.UnsubscribeCount);
1920
Assert.Equal(1, MockState2.UnsubscribeCount);
2021
}
2122

23+
[Fact]
24+
public void WhenBaseOnInitializedWasNotCalled_ThenThrowsNullReferenceException()
25+
{
26+
string errorMessage = null;
27+
var component = new FluxorComponentThatOptionallyCallsBaseOnInitialized();
28+
try
29+
{
30+
component.Test_OnInitialized();
31+
component.Dispose();
32+
}
33+
catch (NullReferenceException e)
34+
{
35+
errorMessage = e.Message;
36+
}
37+
Assert.Equal("Have you forgotten to call base.OnInitialized() in your component?", errorMessage);
38+
}
39+
40+
[Fact]
41+
public void WhenBaseOnInitializedWasCalled_ThenDoesNotThrowAnException()
42+
{
43+
var component = new FluxorComponentThatOptionallyCallsBaseOnInitialized
44+
{
45+
CallBaseOnInitialized = true
46+
};
47+
component.Test_OnInitialized();
48+
component.Dispose();
49+
}
50+
2251
public DisposeTests()
2352
{
2453
MockState1 = new MockState<int>();
2554
MockState2 = new MockState<int>();
26-
Subject = new FluxorComponentWithStateProperties
55+
StateSubject = new FluxorComponentWithStateProperties
2756
{
2857
State1 = MockState1,
2958
State2 = MockState2

Tests/Fluxor.Blazor.Web.UnitTests/Components/FluxorLayoutTests/DisposeTests.cs

+32-4
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,57 @@
11
using Fluxor.Blazor.Web.UnitTests.SupportFiles;
2+
using System;
23
using Xunit;
34

45
namespace Fluxor.Blazor.Web.UnitTests.Components.FluxorLayoutTests
56
{
67
public class DisposeTests
78
{
8-
private readonly FluxorLayoutWithStateProperties Subject;
9+
private readonly FluxorLayoutWithStateProperties StateSubject;
910
private readonly MockState<int> MockState1;
1011
private readonly MockState<int> MockState2;
1112

1213
[Fact]
1314
public void UnsubscribesFromStateProperties()
1415
{
15-
Subject.ExecuteOnInitialized();
16-
Subject.Dispose();
16+
StateSubject.ExecuteOnInitialized();
17+
StateSubject.Dispose();
1718

1819
Assert.Equal(1, MockState1.UnsubscribeCount);
1920
Assert.Equal(1, MockState2.UnsubscribeCount);
2021
}
2122

23+
[Fact]
24+
public void WhenBaseOnInitializedWasNotCalled_ThenThrowsNullReferenceException()
25+
{
26+
string errorMessage = null;
27+
var layout = new FluxorLayoutThatOptionallyCallsBaseOnInitialized();
28+
try
29+
{
30+
layout.Test_OnInitialized();
31+
layout.Dispose();
32+
}
33+
catch (NullReferenceException e)
34+
{
35+
errorMessage = e.Message;
36+
}
37+
Assert.Equal("Have you forgotten to call base.OnInitialized() in your component?", errorMessage);
38+
}
39+
40+
[Fact]
41+
public void WhenBaseOnInitializedWasCalled_ThenDoesNotThrowAnException()
42+
{
43+
var layout = new FluxorLayoutThatOptionallyCallsBaseOnInitialized
44+
{
45+
CallBaseOnInitialized = true
46+
};
47+
layout.Test_OnInitialized();
48+
layout.Dispose();
49+
}
2250
public DisposeTests()
2351
{
2452
MockState1 = new MockState<int>();
2553
MockState2 = new MockState<int>();
26-
Subject = new FluxorLayoutWithStateProperties
54+
StateSubject = new FluxorLayoutWithStateProperties
2755
{
2856
State1 = MockState1,
2957
State2 = MockState2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using Fluxor.Blazor.Web.Components;
2+
3+
namespace Fluxor.Blazor.Web.UnitTests.SupportFiles
4+
{
5+
public class FluxorComponentThatOptionallyCallsBaseOnInitialized : FluxorComponent
6+
{
7+
public bool CallBaseOnInitialized;
8+
9+
protected override void OnInitialized()
10+
{
11+
if (CallBaseOnInitialized)
12+
base.OnInitialized();
13+
}
14+
15+
public void Test_OnInitialized() => OnInitialized();
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using Fluxor.Blazor.Web.Components;
2+
3+
namespace Fluxor.Blazor.Web.UnitTests.SupportFiles
4+
{
5+
public class FluxorLayoutThatOptionallyCallsBaseOnInitialized : FluxorLayout
6+
{
7+
public bool CallBaseOnInitialized;
8+
9+
protected override void OnInitialized()
10+
{
11+
if (CallBaseOnInitialized)
12+
base.OnInitialized();
13+
}
14+
15+
public void Test_OnInitialized() => OnInitialized();
16+
}
17+
}

0 commit comments

Comments
 (0)