Skip to content

Commit 9551a6c

Browse files
ProximystMariell Hoversholm
authored and
Mariell Hoversholm
committed
test: refactor tests
Signed-off-by: Mariell Hoversholm <[email protected]>
1 parent a610c2a commit 9551a6c

File tree

8 files changed

+258
-5
lines changed

8 files changed

+258
-5
lines changed

Diff for: adr/test-file-layout.adoc

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
= Testing file layout
2+
3+
== Summary
4+
5+
=== Issue
6+
7+
Our project requires a standardised file layout for tests. This is necessary because there
8+
are several tests, and they will become rather large due to the nature of the library.
9+
10+
The library prefers using proper classes in actual implementations and usages of it, however
11+
this is not necessarily the case for testing, as they should be as self-contained as possible.
12+
13+
=== Decision
14+
15+
Use a single test per test class with the following structure:
16+
17+
.Structure
18+
[source]
19+
--
20+
src/main/test/<package>
21+
+ <test files>
22+
+ placeholder/
23+
\ <placeholder resolvers and whatnot>
24+
+ util/
25+
\ <util method classes and whatnot>
26+
--
27+
28+
=== Status
29+
30+
Decided. We are open to new alternatives if necessary.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package net.kyori.moonshine;
2+
3+
import static net.kyori.moonshine.util.Unit.UNIT;
4+
import static org.assertj.core.api.Assertions.assertThatCode;
5+
import static org.mockito.ArgumentMatchers.any;
6+
import static org.mockito.Mockito.mock;
7+
import static org.mockito.Mockito.verify;
8+
import static org.mockito.Mockito.when;
9+
10+
import io.leangen.geantyref.TypeToken;
11+
import java.util.Map;
12+
import net.kyori.moonshine.annotation.Message;
13+
import net.kyori.moonshine.annotation.Placeholder;
14+
import net.kyori.moonshine.message.IMessageRenderer;
15+
import net.kyori.moonshine.message.IMessageSender;
16+
import net.kyori.moonshine.message.IMessageSource;
17+
import net.kyori.moonshine.strategy.StandardPlaceholderResolverStrategy;
18+
import net.kyori.moonshine.strategy.supertype.StandardSupertypeThenInterfaceSupertypeStrategy;
19+
import net.kyori.moonshine.util.Unit;
20+
import org.junit.jupiter.api.Test;
21+
22+
@SuppressWarnings("unchecked")
23+
class DefaultMethodTest {
24+
private static final String MESSAGE_KEY = "test";
25+
private static final String DEFAULT_VALUE = "default placeholder value";
26+
27+
@Test
28+
void emptyDefaultMethodTest() throws Exception {
29+
final IMessageSource<Unit, Unit> source = mock(IMessageSource.class);
30+
final IMessageRenderer<Unit, Unit, Unit, Unit> renderer = mock(IMessageRenderer.class);
31+
final IMessageSender<Unit, Unit> sender = mock(IMessageSender.class);
32+
when(source.messageOf(any(), any())).thenReturn(UNIT);
33+
when(renderer.render(any(), any(), any(), any(), any())).thenReturn(UNIT);
34+
35+
assertThatCode(() ->
36+
Moonshine.<TestType, Unit>builder(TypeToken.get(TestType.class))
37+
.receiverLocatorResolver((method, proxy) -> (method1, proxy1, parameters) -> UNIT, 1)
38+
.sourced(source)
39+
.rendered(renderer)
40+
.sent(sender)
41+
.resolvingWithStrategy(new StandardPlaceholderResolverStrategy<>(
42+
new StandardSupertypeThenInterfaceSupertypeStrategy(false)
43+
))
44+
.weightedPlaceholderResolver(String.class,
45+
(placeholderName, value, receiver, owner, method, parameters) -> Map.of(), 1)
46+
.create()
47+
.empty()
48+
).doesNotThrowAnyException();
49+
50+
verify(source).messageOf(UNIT, MESSAGE_KEY);
51+
verify(sender).send(UNIT, UNIT);
52+
}
53+
54+
@Test
55+
void defaultMethodTest() throws Exception {
56+
final IMessageSource<Unit, Unit> source = mock(IMessageSource.class);
57+
final IMessageRenderer<Unit, Unit, Unit, Unit> renderer = mock(IMessageRenderer.class);
58+
final IMessageSender<Unit, Unit> sender = mock(IMessageSender.class);
59+
when(source.messageOf(any(), any())).thenReturn(UNIT);
60+
when(renderer.render(any(), any(), any(), any(), any())).thenReturn(UNIT);
61+
62+
assertThatCode(() ->
63+
Moonshine.<TestType, Unit>builder(TypeToken.get(TestType.class))
64+
.receiverLocatorResolver((method, proxy) -> (method1, proxy1, parameters) -> UNIT, 1)
65+
.sourced(source)
66+
.rendered(renderer)
67+
.sent(sender)
68+
.resolvingWithStrategy(new StandardPlaceholderResolverStrategy<>(
69+
new StandardSupertypeThenInterfaceSupertypeStrategy(false)
70+
))
71+
.weightedPlaceholderResolver(String.class,
72+
(placeholderName, value, receiver, owner, method, parameters) -> Map.of(), 1)
73+
.create()
74+
.withParameter(DEFAULT_VALUE)
75+
).doesNotThrowAnyException();
76+
77+
verify(source).messageOf(UNIT, MESSAGE_KEY);
78+
verify(sender).send(UNIT, UNIT);
79+
}
80+
81+
interface TestType {
82+
@Message(MESSAGE_KEY)
83+
void method(@Placeholder final String placeholder);
84+
85+
default void empty() {
86+
this.method(DEFAULT_VALUE);
87+
}
88+
89+
default void withParameter(final String placeholder) {
90+
this.method(placeholder);
91+
}
92+
}
93+
}
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package net.kyori.moonshine;
2+
3+
import static net.kyori.moonshine.util.Unit.UNIT;
4+
import static org.assertj.core.api.Assertions.assertThatCode;
5+
6+
import io.leangen.geantyref.TypeToken;
7+
import java.util.Map;
8+
import org.junit.jupiter.api.Test;
9+
10+
class EmptyTest {
11+
@Test
12+
void emptyTest() {
13+
assertThatCode(() ->
14+
Moonshine.builder(TypeToken.get(EmptyDefinition.class))
15+
.sourced((receiver, key) -> UNIT)
16+
.rendered((receiver, intermediateMessage, resolvedPlaceholders, method, owner) -> UNIT)
17+
.sent((receiver, renderedMessage) -> {
18+
})
19+
.resolvingWithStrategy((moonshine, receiver, intermediateText, moonshineMethod, parameters) -> Map.of())
20+
.create()
21+
).doesNotThrowAnyException();
22+
}
23+
24+
private interface EmptyDefinition {
25+
}
26+
}

Diff for: core/src/test/java/net/kyori/moonshine/FullMoonshineTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
import org.checkerframework.checker.nullness.qual.Nullable;
5353
import org.junit.jupiter.api.Test;
5454

55-
/* package-private */ class FullMoonshineTest {
55+
class FullMoonshineTest {
5656
@Test
5757
void fullyFledgedMoonshineInstance() throws Exception {
5858
final MockedReceiver receiver = mock(MockedReceiver.class);

Diff for: core/src/test/java/net/kyori/moonshine/SimpleMoonshineTest.java

+49-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
package net.kyori.moonshine;
1919

2020
import static java.util.Collections.emptyMap;
21-
import static net.kyori.moonshine.Unit.UNIT;
21+
import static net.kyori.moonshine.util.Unit.UNIT;
2222
import static org.assertj.core.api.Assertions.assertThatCode;
2323
import static org.assertj.core.api.Assertions.fail;
2424
import static org.mockito.ArgumentMatchers.any;
@@ -44,6 +44,7 @@
4444
import net.kyori.moonshine.strategy.StandardPlaceholderResolverStrategy;
4545
import net.kyori.moonshine.strategy.supertype.StandardSupertypeThenInterfaceSupertypeStrategy;
4646
import net.kyori.moonshine.util.Either;
47+
import net.kyori.moonshine.util.Unit;
4748
import org.checkerframework.checker.nullness.qual.Nullable;
4849
import org.junit.jupiter.api.Test;
4950

@@ -75,7 +76,7 @@ void singleEmptyMethod() throws Exception {
7576

7677
assertThatCode(() ->
7778
Moonshine.<SingleEmptyMethodMoonshineType, Unit>builder(
78-
TypeToken.get(SingleEmptyMethodMoonshineType.class))
79+
TypeToken.get(SingleEmptyMethodMoonshineType.class))
7980
.receiverLocatorResolver((method, proxy) -> (method1, proxy1, parameters) -> UNIT,
8081
2)
8182
.sourced(messageSource)
@@ -99,7 +100,7 @@ void singleMethodStringPlaceholders() throws Exception {
99100

100101
assertThatCode(() ->
101102
Moonshine.<SingleMethodStringPlaceholdersMoonshineType, TestableReceiver>builder(
102-
TypeToken.get(SingleMethodStringPlaceholdersMoonshineType.class))
103+
TypeToken.get(SingleMethodStringPlaceholdersMoonshineType.class))
103104
.receiverLocatorResolver((method, proxy) -> (method1, proxy1, parameters) -> receiver,
104105
-1)
105106
.sourced(messageSource)
@@ -131,6 +132,39 @@ void singleMethodStringPlaceholders() throws Exception {
131132
verify(messageSender).send(receiver, "Hello, second!");
132133
}
133134

135+
@Test
136+
void defaultMethodOneParam() throws Exception {
137+
final IMessageSource<TestableReceiver, String> messageSource = mock(IMessageSource.class);
138+
final IMessageRenderer<TestableReceiver, String, String, String> messageRenderer = spy(
139+
new SimpleStringFormatRenderer<>());
140+
final IMessageSender<TestableReceiver, String> messageSender = mock(IMessageSender.class);
141+
final TestableReceiver receiver = mock(TestableReceiver.class);
142+
when(messageSource.messageOf(any(), any())).thenReturn("Hello, %1$s!");
143+
144+
assertThatCode(() ->
145+
Moonshine.<DefaultMethodNoParams, TestableReceiver>builder(TypeToken.get(DefaultMethodNoParams.class))
146+
.receiverLocatorResolver((method, proxy) -> (method1, proxy1, parameters) -> receiver, -1)
147+
.sourced(messageSource)
148+
.rendered(messageRenderer)
149+
.sent(messageSender)
150+
.resolvingWithStrategy(new StandardPlaceholderResolverStrategy<>(
151+
new StandardSupertypeThenInterfaceSupertypeStrategy(false)
152+
))
153+
.weightedPlaceholderResolver(String.class,
154+
(placeholderName, value, receiver1, owner, method, parameters) ->
155+
Map.of(placeholderName, Either.left(ConclusionValue.conclusionValue(value))), 1)
156+
.create()
157+
.method(receiver)
158+
).doesNotThrowAnyException();
159+
160+
verify(messageSource).messageOf(receiver, "test");
161+
verify(messageRenderer).render(receiver, "Hello, %1$s!",
162+
new LinkedHashMap<>(Map.of("placeholder", "placeholder value")),
163+
DefaultMethodNoParams.class.getMethods()[0],
164+
TypeToken.get(DefaultMethodNoParams.class).getType());
165+
verify(messageSender).send(receiver, "Hello, placeholder value!");
166+
}
167+
134168
interface EmptyMoonshineType {
135169
}
136170

@@ -148,6 +182,18 @@ void method(
148182
);
149183
}
150184

185+
interface DefaultMethodNoParams {
186+
@Message("test")
187+
void method(
188+
final TestableReceiver receiver,
189+
@Placeholder final String placeholder
190+
);
191+
192+
default void method(final TestableReceiver receiver) {
193+
this.method(receiver, "placeholder value");
194+
}
195+
}
196+
151197
private static class TestableReceiver {
152198
void send(final Object message) {
153199
fail("TestableReceiver#send must be mocked");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package net.kyori.moonshine;
2+
3+
import static net.kyori.moonshine.util.Unit.UNIT;
4+
import static org.assertj.core.api.Assertions.assertThatCode;
5+
import static org.mockito.ArgumentMatchers.any;
6+
import static org.mockito.Mockito.mock;
7+
import static org.mockito.Mockito.verify;
8+
import static org.mockito.Mockito.when;
9+
10+
import io.leangen.geantyref.TypeToken;
11+
import net.kyori.moonshine.annotation.Message;
12+
import net.kyori.moonshine.message.IMessageRenderer;
13+
import net.kyori.moonshine.message.IMessageSender;
14+
import net.kyori.moonshine.message.IMessageSource;
15+
import net.kyori.moonshine.strategy.StandardPlaceholderResolverStrategy;
16+
import net.kyori.moonshine.strategy.supertype.StandardSupertypeThenInterfaceSupertypeStrategy;
17+
import net.kyori.moonshine.util.Unit;
18+
import org.junit.jupiter.api.Test;
19+
20+
@SuppressWarnings("unchecked")
21+
class SingleEmptyMethodTest {
22+
private static final String MESSAGE_KEY = "test";
23+
24+
@Test
25+
void simpleEmptyMethodMoonshineTest() throws Exception {
26+
final IMessageSource<Unit, Unit> source = mock(IMessageSource.class);
27+
final IMessageRenderer<Unit, Unit, Unit, Unit> renderer = mock(IMessageRenderer.class);
28+
final IMessageSender<Unit, Unit> sender = mock(IMessageSender.class);
29+
when(source.messageOf(any(), any())).thenReturn(UNIT);
30+
when(renderer.render(any(), any(), any(), any(), any())).thenReturn(UNIT);
31+
32+
assertThatCode(() ->
33+
Moonshine.<SimpleType, Unit>builder(TypeToken.get(SimpleType.class))
34+
.receiverLocatorResolver((method, proxy) -> (method1, proxy1, parameters) -> UNIT, 1)
35+
.sourced(source)
36+
.rendered(renderer)
37+
.sent(sender)
38+
.resolvingWithStrategy(new StandardPlaceholderResolverStrategy<>(
39+
new StandardSupertypeThenInterfaceSupertypeStrategy(false)
40+
))
41+
.create()
42+
.method()
43+
).doesNotThrowAnyException();
44+
45+
verify(source).messageOf(UNIT, MESSAGE_KEY);
46+
verify(sender).send(UNIT, UNIT);
47+
}
48+
49+
interface SimpleType {
50+
@Message(MESSAGE_KEY)
51+
void method();
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package net.kyori.moonshine.util;
2+
3+
public interface Receiver {
4+
void send(final Object message);
5+
}

Diff for: core/src/test/java/net/kyori/moonshine/Unit.java renamed to core/src/test/java/net/kyori/moonshine/util/Unit.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* You should have received a copy of the GNU Lesser General Public License
1616
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
18-
package net.kyori.moonshine;
18+
package net.kyori.moonshine.util;
1919

2020
public enum Unit {
2121
UNIT

0 commit comments

Comments
 (0)