1
+ //-----------------------------------------------------------------------
2
+ // <copyright file="ActorWithStashSpec.cs" company="Akka.NET Project">
3
+ // Copyright (C) 2013-2023 .NET Foundation <https://github.com/akkadotnet/akka.net>
4
+ // </copyright>
5
+ //-----------------------------------------------------------------------
6
+
7
+ using Akka . Actor ;
8
+ using Akka . TestKit ;
9
+ using FluentAssertions ;
10
+ using FluentAssertions . Extensions ;
11
+ using Xunit ;
12
+ using Xunit . Abstractions ;
13
+
14
+ namespace Akka . DependencyInjection . Tests ;
15
+
16
+ public class ActorWithStashSpec : AkkaSpec , IClassFixture < AkkaDiFixture >
17
+ {
18
+ public ActorWithStashSpec ( AkkaDiFixture fixture , ITestOutputHelper output )
19
+ : base (
20
+ DependencyResolverSetup . Create ( fixture . Provider )
21
+ . And ( BootstrapSetup . Create ( ) . WithConfig ( TestKitBase . DefaultConfig ) ) ,
22
+ output )
23
+ {
24
+ }
25
+
26
+ [ Fact ( DisplayName = "DependencyInjection should create actor with IWithStash interface" ) ]
27
+ public void WithStashActorTest ( )
28
+ {
29
+ var stashActor = GetActorOf < WithStashActor > ( Sys ) ;
30
+
31
+ stashActor . Tell ( GetName . Instance , TestActor ) ;
32
+ ExpectNoMsg ( 0.3 . Seconds ( ) ) ;
33
+ stashActor . Tell ( GetName . Instance , TestActor ) ;
34
+ ExpectNoMsg ( 0.3 . Seconds ( ) ) ;
35
+
36
+ stashActor . Tell ( StartProcessing . Instance , TestActor ) ;
37
+ ExpectMsg < string > ( ) . Should ( ) . StartWith ( "s" ) ;
38
+ ExpectMsg < string > ( ) . Should ( ) . StartWith ( "s" ) ;
39
+ ExpectNoMsg ( 0.3 . Seconds ( ) ) ;
40
+ }
41
+
42
+ [ Fact ( DisplayName = "DependencyInjection should create actor with IWithUnboundedStash interface" ) ]
43
+ public void WithUnboundedStashActorTest ( )
44
+ {
45
+ var stashActor = GetActorOf < WithUnboundedStashActor > ( Sys ) ;
46
+
47
+ stashActor . Tell ( GetName . Instance , TestActor ) ;
48
+ ExpectNoMsg ( 0.3 . Seconds ( ) ) ;
49
+ stashActor . Tell ( GetName . Instance , TestActor ) ;
50
+ ExpectNoMsg ( 0.3 . Seconds ( ) ) ;
51
+
52
+ stashActor . Tell ( StartProcessing . Instance , TestActor ) ;
53
+ ExpectMsg < string > ( ) . Should ( ) . StartWith ( "s" ) ;
54
+ ExpectMsg < string > ( ) . Should ( ) . StartWith ( "s" ) ;
55
+ ExpectNoMsg ( 0.3 . Seconds ( ) ) ;
56
+ }
57
+
58
+ [ Fact ( DisplayName = "DependencyInjection should create child actor with IWithStash interface" ) ]
59
+ public void WithStashChildActorTest ( )
60
+ {
61
+ var parentActor = Sys . ActorOf ( Props . Create ( ( ) => new ParentActor < WithStashActor > ( ) ) ) ;
62
+
63
+ parentActor . Tell ( GetName . Instance , TestActor ) ;
64
+ ExpectNoMsg ( 0.3 . Seconds ( ) ) ;
65
+ parentActor . Tell ( GetName . Instance , TestActor ) ;
66
+ ExpectNoMsg ( 0.3 . Seconds ( ) ) ;
67
+
68
+ parentActor . Tell ( StartProcessing . Instance , TestActor ) ;
69
+ ExpectMsg < string > ( ) . Should ( ) . StartWith ( "s" ) ;
70
+ ExpectMsg < string > ( ) . Should ( ) . StartWith ( "s" ) ;
71
+ ExpectNoMsg ( 0.3 . Seconds ( ) ) ;
72
+ }
73
+
74
+ [ Fact ( DisplayName = "DependencyInjection should create child actor with IWithUnboundedStash interface" ) ]
75
+ public void WithUnboundedStashChildActorTest ( )
76
+ {
77
+ var parentActor = Sys . ActorOf ( Props . Create ( ( ) => new ParentActor < WithUnboundedStashActor > ( ) ) ) ;
78
+
79
+ parentActor . Tell ( GetName . Instance , TestActor ) ;
80
+ ExpectNoMsg ( 0.3 . Seconds ( ) ) ;
81
+ parentActor . Tell ( GetName . Instance , TestActor ) ;
82
+ ExpectNoMsg ( 0.3 . Seconds ( ) ) ;
83
+
84
+ parentActor . Tell ( StartProcessing . Instance , TestActor ) ;
85
+ ExpectMsg < string > ( ) . Should ( ) . StartWith ( "s" ) ;
86
+ ExpectMsg < string > ( ) . Should ( ) . StartWith ( "s" ) ;
87
+ ExpectNoMsg ( 0.3 . Seconds ( ) ) ;
88
+ }
89
+
90
+ private static IActorRef GetActorOf < T > ( ActorSystem actorSystem ) where T : ActorBase
91
+ => actorSystem . ActorOf ( DependencyResolver . For ( actorSystem ) . Props < T > ( ) ) ;
92
+
93
+ private static IActorRef GetActorOf < T > ( IActorContext actorContext , ActorSystem actorSystem ) where T : ActorBase
94
+ => actorContext . ActorOf ( DependencyResolver . For ( actorSystem ) . Props < T > ( ) ) ;
95
+
96
+ private sealed class WithStashActor : StashingActor , IWithStash
97
+ {
98
+ public WithStashActor ( AkkaDiFixture . IScopedDependency scoped ) : base ( scoped )
99
+ {
100
+ }
101
+ }
102
+
103
+ private sealed class WithUnboundedStashActor : StashingActor , IWithUnboundedStash
104
+ {
105
+ public WithUnboundedStashActor ( AkkaDiFixture . IScopedDependency scoped ) : base ( scoped )
106
+ {
107
+ }
108
+ }
109
+
110
+ private sealed class ParentActor < T > : ReceiveActor where T : StashingActor
111
+ {
112
+ public ParentActor ( )
113
+ {
114
+ var child = GetActorOf < T > ( Context , Context . System ) ;
115
+ ReceiveAny ( msg => child . Forward ( msg ) ) ;
116
+ }
117
+ }
118
+
119
+ private abstract class StashingActor : ReceiveActor
120
+ {
121
+ private readonly AkkaDiFixture . IScopedDependency _scoped ;
122
+
123
+ protected StashingActor ( AkkaDiFixture . IScopedDependency scoped )
124
+ {
125
+ _scoped = scoped ;
126
+ Become ( Stashing ) ;
127
+ }
128
+
129
+ private bool Stashing ( object message )
130
+ {
131
+ if ( message is StartProcessing )
132
+ {
133
+ Become ( Processing ) ;
134
+ Stash . UnstashAll ( ) ;
135
+ return true ;
136
+ }
137
+
138
+ Stash . Stash ( ) ;
139
+ return true ;
140
+ }
141
+
142
+ private bool Processing ( object message )
143
+ {
144
+ if ( message is GetName )
145
+ {
146
+ Sender . Tell ( _scoped . Name ) ;
147
+ return true ;
148
+ }
149
+
150
+ return false ;
151
+ }
152
+
153
+ public IStash Stash { get ; set ; }
154
+ }
155
+
156
+ private sealed class GetName
157
+ {
158
+ public static readonly GetName Instance = new ( ) ;
159
+ private GetName ( ) { }
160
+ }
161
+
162
+ private sealed class StartProcessing
163
+ {
164
+ public static readonly StartProcessing Instance = new ( ) ;
165
+ private StartProcessing ( ) { }
166
+ }
167
+ }
0 commit comments