Upgrade to Spring Boot 3.4.0-M3 (#6687)

#### What type of PR is this?

/kind cleanup
/area core
/milestone 2.20.x

#### What this PR does / why we need it:

This PR upgrades to [Spring Boot 3.4.0-M3](https://github.com/spring-projects/spring-boot/releases/tag/v3.4.0-M3).

1. Fix the compilation error of OptimalPropertyAccess because the class has been privated in [this commit](b431594021).
2. Fix exception `org.mockito.exceptions.misusing.UnnecessaryStubbingException` for some unit tests after upgrading.
3. Replace deprecated annotations `@MockBean` and `@SpyBean` with `@MockitoBean` and `@MockitoSpyBean` respectively.

#### Does this PR introduce a user-facing change?

```release-note
升级 Spring Boot 至 3.4.0-M3
```
pull/6696/head
John Niang 2024-09-24 15:01:22 +08:00 committed by GitHub
parent 035207b8db
commit 86b95ccfd0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 141 additions and 139 deletions

View File

@ -12,6 +12,7 @@ import org.springframework.expression.MethodExecutor;
import org.springframework.expression.MethodResolver;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
import org.springframework.expression.spel.CompilablePropertyAccessor;
import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
import org.springframework.integration.json.JsonPropertyAccessor;
import org.springframework.lang.Nullable;
@ -122,7 +123,7 @@ public class EvaluationContextEnhancer extends AbstractTemplateBoundariesProcess
public PropertyAccessor createOptimalAccessor(EvaluationContext context, Object target,
String name) {
var optimalAccessor = delegate.createOptimalAccessor(context, target, name);
if (optimalAccessor instanceof OptimalPropertyAccessor optimalPropertyAccessor) {
if (optimalAccessor instanceof CompilablePropertyAccessor optimalPropertyAccessor) {
if (ReactiveUtils.isReactiveType(optimalPropertyAccessor.getPropertyType())) {
return this;
}

View File

@ -19,10 +19,10 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.reactive.server.WebTestClient;
import reactor.core.publisher.Flux;
import run.halo.app.core.extension.Role;
@ -47,7 +47,7 @@ class ExtensionConfigurationTest {
@Autowired
SchemeManager schemeManager;
@MockBean
@MockitoBean
RoleService roleService;
@BeforeEach

View File

@ -13,10 +13,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketMessage;
@ -38,7 +38,7 @@ class WebFluxConfigTest {
@Autowired
WebTestClient webClient;
@SpyBean
@MockitoSpyBean
RoleService roleService;
@LocalServerPort

View File

@ -12,8 +12,8 @@ import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@ -46,7 +46,7 @@ class CategoryPostCountUpdaterTest {
@Autowired
private SchemeManager schemeManager;
@SpyBean
@MockitoSpyBean
private ExtensionClient client;
@Autowired

View File

@ -12,9 +12,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.reactive.server.WebTestClient;
import reactor.core.publisher.Flux;
import run.halo.app.core.extension.Role;
@ -39,7 +39,7 @@ public class PostIntegrationTests {
@Autowired
private WebTestClient webTestClient;
@MockBean
@MockitoBean
RoleService roleService;
@BeforeEach

View File

@ -14,8 +14,8 @@ import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@ -48,7 +48,7 @@ class CommentServiceImplIntegrationTest {
@Autowired
private SchemeManager schemeManager;
@SpyBean
@MockitoSpyBean
private ReactiveExtensionClient reactiveClient;
@Autowired
@ -57,7 +57,7 @@ class CommentServiceImplIntegrationTest {
@Autowired
private IndexerFactory indexerFactory;
@SpyBean
@MockitoSpyBean
private CommentServiceImpl commentService;
Mono<Extension> deleteImmediately(Extension extension) {

View File

@ -2,7 +2,6 @@ package run.halo.app.content.comment;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@ -12,7 +11,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.json.JSONException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
@ -61,53 +59,25 @@ import run.halo.app.security.authorization.AuthorityUtils;
class CommentServiceImplTest {
@Mock
private SystemConfigurableEnvironmentFetcher environmentFetcher;
SystemConfigurableEnvironmentFetcher environmentFetcher;
@Mock
private ReactiveExtensionClient client;
ReactiveExtensionClient client;
@Mock
private UserService userService;
UserService userService;
@Mock
private RoleService roleService;
RoleService roleService;
@Mock
private ExtensionGetter extensionGetter;
ExtensionGetter extensionGetter;
@InjectMocks
private CommentServiceImpl commentService;
CommentServiceImpl commentService;
@Mock
private CounterService counterService;
@BeforeEach
void setUp() {
SystemSetting.Comment commentSetting = getCommentSetting();
lenient().when(environmentFetcher.fetchComment()).thenReturn(Mono.just(commentSetting));
ListResult<Comment> comments = new ListResult<>(1, 10, 3, comments());
when(client.listBy(eq(Comment.class), any(ListOptions.class), any(PageRequest.class)))
.thenReturn(Mono.just(comments));
when(userService.getUserOrGhost(eq("A-owner")))
.thenReturn(Mono.just(createUser("A-owner")));
when(userService.getUserOrGhost(eq("B-owner")))
.thenReturn(Mono.just(createUser("B-owner")));
when(client.fetch(eq(User.class), eq("C-owner")))
.thenReturn(Mono.empty());
when(roleService.contains(Set.of("USER"),
Set.of(AuthorityUtils.COMMENT_MANAGEMENT_ROLE_NAME)))
.thenReturn(Mono.just(false));
PostCommentSubject postCommentSubject = Mockito.mock(PostCommentSubject.class);
when(extensionGetter.getExtensions(CommentSubject.class))
.thenReturn(Flux.just(postCommentSubject));
when(postCommentSubject.supports(any())).thenReturn(true);
when(postCommentSubject.get(eq("fake-post"))).thenReturn(Mono.just(post()));
}
CounterService counterService;
private static User createUser(String name) {
User user = new User();
@ -122,10 +92,21 @@ class CommentServiceImplTest {
@Test
void listComment() {
var comments = new ListResult<Comment>(1, 10, 3, comments());
when(client.listBy(eq(Comment.class), any(ListOptions.class), any(PageRequest.class)))
.thenReturn(Mono.just(comments));
PostCommentSubject postCommentSubject = Mockito.mock(PostCommentSubject.class);
when(extensionGetter.getExtensions(CommentSubject.class))
.thenReturn(Flux.just(postCommentSubject));
when(postCommentSubject.supports(any())).thenReturn(true);
when(postCommentSubject.get(eq("fake-post"))).thenReturn(Mono.just(post()));
when(userService.getUserOrGhost(any()))
.thenReturn(Mono.just(ghostUser()));
when(userService.getUserOrGhost("A-owner"))
.thenReturn(Mono.just(createUser("A-owner")));
// when(userService.getUserOrGhost("A-owner"))
// .thenReturn(Mono.just(createUser("A-owner")));
when(userService.getUserOrGhost("B-owner"))
.thenReturn(Mono.just(createUser("B-owner")));
@ -170,6 +151,12 @@ class CommentServiceImplTest {
@Test
@WithMockUser(username = "B-owner")
void create() throws JSONException {
var commentSetting = getCommentSetting();
when(environmentFetcher.fetchComment()).thenReturn(Mono.just(commentSetting));
when(roleService.contains(Set.of("USER"),
Set.of(AuthorityUtils.COMMENT_MANAGEMENT_ROLE_NAME)))
.thenReturn(Mono.just(false));
CommentRequest commentRequest = new CommentRequest();
commentRequest.setRaw("fake-raw");
commentRequest.setContent("fake-content");

View File

@ -14,8 +14,8 @@ import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
@ -56,7 +56,7 @@ class ReplyServiceImplIntegrationTest {
@Autowired
private SchemeManager schemeManager;
@SpyBean
@MockitoSpyBean
private ReactiveExtensionClient reactiveClient;
@Autowired
@ -65,7 +65,7 @@ class ReplyServiceImplIntegrationTest {
@Autowired
private IndexerFactory indexerFactory;
@SpyBean
@MockitoSpyBean
private ReplyServiceImpl replyService;
Mono<Extension> deleteImmediately(Extension extension) {

View File

@ -1,15 +1,11 @@
package run.halo.app.core.endpoint.console;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.csrf;
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity;
import io.github.resilience4j.ratelimiter.RateLimiterConfig;
import io.github.resilience4j.ratelimiter.RateLimiterRegistry;
import io.github.resilience4j.reactor.ratelimiter.operator.RateLimiterOperator;
import java.time.Duration;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
@ -39,47 +35,49 @@ import run.halo.app.extension.ReactiveExtensionClient;
@ExtendWith(SpringExtension.class)
@WithMockUser(username = "fake-user", password = "fake-password")
class EmailVerificationCodeTest {
WebTestClient webClient;
@Mock
ReactiveExtensionClient client;
@Mock
EmailVerificationService emailVerificationService;
@Mock
UserService userService;
@Mock
RateLimiterRegistry rateLimiterRegistry;
@InjectMocks
UserEndpoint endpoint;
@BeforeEach
void setUp() {
var spyUserEndpoint = spy(endpoint);
webClient = WebTestClient.bindToRouterFunction(endpoint.endpoint())
.apply(springSecurity())
.build();
}
@Test
void sendEmailVerificationCode() {
var config = RateLimiterConfig.custom()
.limitRefreshPeriod(Duration.ofSeconds(10))
.limitForPeriod(1)
.build();
var sendCodeRateLimiter = RateLimiterRegistry.of(config)
.rateLimiter("send-email-verification-code-fake-user:hi@halo.run");
doReturn(RateLimiterOperator.of(sendCodeRateLimiter)).when(spyUserEndpoint)
.sendEmailVerificationCodeRateLimiter(eq("fake-user"), eq("hi@halo.run"));
when(rateLimiterRegistry.rateLimiter(
"send-email-verification-code-fake-user:hi@halo.run",
"send-email-verification-code")
).thenReturn(sendCodeRateLimiter);
var verifyEmailRateLimiter = RateLimiterRegistry.of(config)
.rateLimiter("verify-email-fake-user");
doReturn(RateLimiterOperator.of(verifyEmailRateLimiter)).when(spyUserEndpoint)
.verificationEmailRateLimiter(eq("fake-user"));
webClient = WebTestClient.bindToRouterFunction(spyUserEndpoint.endpoint()).build()
.mutateWith(csrf());
}
@Test
void sendEmailVerificationCode() {
var user = new User();
user.setMetadata(new Metadata());
user.getMetadata().setName("fake-user");
user.setSpec(new User.UserSpec());
user.getSpec().setEmail("hi@halo.run");
when(client.get(eq(User.class), eq("fake-user"))).thenReturn(Mono.just(user));
when(emailVerificationService.sendVerificationCode(anyString(), anyString()))
.thenReturn(Mono.empty());
webClient.post()
@ -100,6 +98,16 @@ class EmailVerificationCodeTest {
@Test
void verifyEmail() {
var config = RateLimiterConfig.custom()
.limitRefreshPeriod(Duration.ofSeconds(10))
.limitForPeriod(1)
.build();
var verifyEmailRateLimiter = RateLimiterRegistry.of(config)
.rateLimiter("verify-email-fake-user");
when(rateLimiterRegistry.rateLimiter("verify-email-fake-user", "verify-email"))
.thenReturn(verifyEmailRateLimiter);
when(emailVerificationService.verify(anyString(), anyString()))
.thenReturn(Mono.empty());
when(userService.confirmPassword(anyString(), anyString()))

View File

@ -14,9 +14,9 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.reactive.server.WebTestClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@ -37,7 +37,7 @@ public class UserEndpointIntegrationTest {
@Autowired
ReactiveExtensionClient client;
@MockBean
@MockitoBean
RoleService roleService;
@BeforeEach

View File

@ -9,13 +9,13 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pf4j.PluginWrapper;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import run.halo.app.search.SearchService;
@SpringBootTest
class DefaultPluginApplicationContextFactoryTest {
@SpyBean
@MockitoSpyBean
SpringPluginManager pluginManager;
DefaultPluginApplicationContextFactory factory;

View File

@ -23,11 +23,11 @@ import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import org.skyscreamer.jsonassert.JSONAssert;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.Plugin;
import run.halo.app.extension.ConfigMap;
@ -55,7 +55,7 @@ class DefaultSettingFetcherTest {
@Mock
private CacheManager cacheManager;
@MockBean
@MockitoBean
private final PluginContext pluginContext = PluginContext.builder()
.name("fake")
.configMapName("fake-config")

View File

@ -37,11 +37,12 @@ import run.halo.app.infra.utils.JsonUtils;
*/
@ExtendWith(SpringExtension.class)
class AuthProviderServiceImplTest {
@Mock
private ReactiveExtensionClient client;
ReactiveExtensionClient client;
@InjectMocks
private AuthProviderServiceImpl authProviderService;
AuthProviderServiceImpl authProviderService;
@Test
void testEnable() {
@ -57,14 +58,12 @@ class AuthProviderServiceImplTest {
when(client.fetch(eq(ConfigMap.class), eq(SystemSetting.SYSTEM_CONFIG)))
.thenReturn(Mono.just(configMap));
AuthProvider local = createAuthProvider("local");
local.getMetadata().getLabels().put(AuthProvider.PRIVILEGED_LABEL, "true");
when(client.list(eq(AuthProvider.class), any(), any())).thenReturn(Flux.just(local));
// Call the method being tested
Mono<AuthProvider> result = authProviderService.enable("github");
authProviderService.enable("github")
.as(StepVerifier::create)
.expectNext(authProvider)
.verifyComplete();
assertEquals(authProvider, result.block());
ConfigMap value = captor.getValue();
String providerSettingStr = value.getData().get(SystemSetting.AuthProvider.GROUP);
Set<String> enabled =
@ -84,7 +83,7 @@ class AuthProviderServiceImplTest {
AuthProvider local = createAuthProvider("local");
local.getMetadata().getLabels().put(AuthProvider.PRIVILEGED_LABEL, "true");
when(client.list(eq(AuthProvider.class), any(), any())).thenReturn(Flux.just(local));
// when(client.list(eq(AuthProvider.class), any(), any())).thenReturn(Flux.just(local));
ArgumentCaptor<ConfigMap> captor = ArgumentCaptor.forClass(ConfigMap.class);
when(client.update(captor.capture())).thenReturn(Mono.empty());
@ -155,7 +154,7 @@ class AuthProviderServiceImplTest {
"supportsBinding": false,
"privileged": false
},{
"name": "gitee",
"displayName": "gitee",
"enabled": false,

View File

@ -10,8 +10,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import org.springframework.test.web.reactive.server.WebTestClient;
import run.halo.app.core.extension.Role;
import run.halo.app.core.extension.RoleBinding;
@ -28,7 +28,7 @@ import run.halo.app.extension.ReactiveExtensionClient;
@AutoConfigureTestDatabase
class SuperAdminInitializerTest {
@SpyBean
@MockitoSpyBean
ReactiveExtensionClient client;
@Autowired

View File

@ -17,7 +17,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
@ -26,6 +25,7 @@ import org.springframework.security.core.userdetails.ReactiveUserDetailsPassword
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
@ -49,13 +49,13 @@ class AuthorizationTest {
@Autowired
WebTestClient webClient;
@SpyBean
@MockitoSpyBean
ReactiveUserDetailsService userDetailsService;
@SpyBean
@MockitoSpyBean
ReactiveUserDetailsPasswordService userDetailsPasswordService;
@SpyBean
@MockitoSpyBean
RoleService roleService;
@Autowired

View File

@ -11,11 +11,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
@ -36,7 +36,7 @@ public class ThemeIntegrationTest {
@Autowired
WebTestClient webClient;
@MockBean
@MockitoBean
InitializationStateGetter initializationStateGetter;
@Autowired

View File

@ -2,14 +2,13 @@ package run.halo.app.theme;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ -35,40 +34,41 @@ import reactor.test.StepVerifier;
class ViewNameResolverTest {
@Mock
private ThemeResolver themeResolver;
ThemeResolver themeResolver;
@Mock
private ThymeleafProperties thymeleafProperties;
ThymeleafProperties thymeleafProperties;
@InjectMocks
private DefaultViewNameResolver viewNameResolver;
DefaultViewNameResolver viewNameResolver;
@TempDir
private File themePath;
Path themePath;
@BeforeEach
void setUp() throws IOException {
when(thymeleafProperties.getSuffix()).thenReturn(ThymeleafProperties.DEFAULT_SUFFIX);
}
var templatesPath = themePath.toPath().resolve("templates");
@Test
void resolveViewNameOrDefault() throws URISyntaxException, IOException {
var templatesPath = themePath.resolve("templates");
if (!Files.exists(templatesPath)) {
Files.createDirectory(templatesPath);
}
Files.createFile(templatesPath.resolve("post_news.html"));
Files.createFile(templatesPath.resolve("post_docs.html"));
when(themeResolver.getTheme(any()))
var exchange = Mockito.mock(ServerWebExchange.class);
when(themeResolver.getTheme(exchange))
.thenReturn(Mono.fromSupplier(() -> ThemeContext.builder()
.name("fake-theme")
.path(themePath.toPath())
.path(themePath)
.active(true)
.build())
);
}
@Test
void resolveViewNameOrDefault() throws URISyntaxException {
ServerWebExchange exchange = Mockito.mock(ServerWebExchange.class);
MockServerRequest request = MockServerRequest.builder()
.uri(new URI("/")).method(HttpMethod.GET)
.exchange(exchange)

View File

@ -11,7 +11,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.util.ResourceUtils;
import org.springframework.web.server.ServerWebExchange;
@ -27,10 +27,10 @@ class GeneratorMetaProcessorTest {
@Autowired
WebTestClient webClient;
@MockBean
@MockitoBean
InitializationStateGetter initializationStateGetter;
@MockBean
@MockitoBean
ThemeResolver themeResolver;
@BeforeEach

View File

@ -44,21 +44,19 @@ import run.halo.app.metrics.CounterService;
class CommentPublicQueryServiceImplTest {
@Mock
private ReactiveExtensionClient client;
@Mock
private UserService userService;
ReactiveExtensionClient client;
@Mock
private CounterService counterService;
UserService userService;
@Mock
CounterService counterService;
@InjectMocks
private CommentPublicQueryServiceImpl commentPublicQueryService;
CommentPublicQueryServiceImpl commentPublicQueryService;
@BeforeEach
void setUp() {
User ghost = createUser();
ghost.getMetadata().setName("ghost");
when(userService.getUserOrGhost(eq("ghost"))).thenReturn(Mono.just(ghost));
when(userService.getUserOrGhost(eq("fake-user"))).thenReturn(Mono.just(createUser()));
}

View File

@ -13,9 +13,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.util.ResourceUtils;
import org.springframework.web.reactive.function.server.RequestPredicates;
@ -38,14 +38,14 @@ import run.halo.app.theme.ThemeResolver;
@AutoConfigureWebTestClient
public class ThemeMessageResolverIntegrationTest {
@SpyBean
@MockitoSpyBean
private ThemeResolver themeResolver;
private URL defaultThemeUrl;
private URL otherThemeUrl;
@SpyBean
@MockitoSpyBean
private InitializationStateGetter initializationStateGetter;
@Autowired

View File

@ -43,36 +43,40 @@ import run.halo.app.theme.finders.vo.SinglePageVo;
@ExtendWith(SpringExtension.class)
class PreviewRouterFunctionTest {
@Mock
private ReactiveExtensionClient client;
ReactiveExtensionClient client;
@Mock
private PostPublicQueryService postPublicQueryService;
PostPublicQueryService postPublicQueryService;
@Mock
private ViewNameResolver viewNameResolver;
ViewNameResolver viewNameResolver;
@Mock
private ViewResolver viewResolver;
ViewResolver viewResolver;
@Mock
private PostService postService;
PostService postService;
@Mock
private SinglePageConversionService singlePageConversionService;
SinglePageConversionService singlePageConversionService;
@InjectMocks
private PreviewRouterFunction previewRouterFunction;
PreviewRouterFunction previewRouterFunction;
private WebTestClient webTestClient;
WebTestClient webTestClient;
@BeforeEach
public void setUp() {
void setUp() {
webTestClient = WebTestClient.bindToRouterFunction(previewRouterFunction.previewRouter())
.handlerStrategies(HandlerStrategies.builder()
.viewResolver(viewResolver)
.build())
.build();
}
@Test
@WithMockUser(username = "testuser")
void previewPost() {
when(viewResolver.resolveViewName(any(), any()))
.thenReturn(Mono.just(new EmptyView() {
@Override
@ -81,11 +85,7 @@ class PreviewRouterFunctionTest {
return super.render(model, contentType, exchange);
}
}));
}
@Test
@WithMockUser(username = "testuser")
public void previewPost() {
Post post = new Post();
post.setMetadata(new Metadata());
post.getMetadata().setName("post1");
@ -123,6 +123,15 @@ class PreviewRouterFunctionTest {
@Test
@WithMockUser(username = "testuser")
public void previewSinglePage() {
when(viewResolver.resolveViewName(any(), any()))
.thenReturn(Mono.just(new EmptyView() {
@Override
public Mono<Void> render(Map<String, ?> model, MediaType contentType,
ServerWebExchange exchange) {
return super.render(model, contentType, exchange);
}
}));
SinglePage singlePage = new SinglePage();
singlePage.setMetadata(new Metadata());
singlePage.getMetadata().setName("page1");

View File

@ -1,5 +1,5 @@
plugins {
id 'org.springframework.boot' version '3.3.3' apply false
id 'org.springframework.boot' version '3.4.0-M3' apply false
id 'io.spring.dependency-management' version '1.1.6' apply false
id "com.gorylenko.gradle-git-properties" version "2.4.1" apply false
id "de.undercouch.download" version "5.6.0" apply false