SpringBootTest中如何Mock GraphServiceClient实现Azure AD B2C用户创建测试
如何Mock GraphServiceClient测试Azure AD B2C用户创建方法?
我在应用中实现了一个通过Microsoft Graph REST API在Azure AD B2C创建用户的Java方法,现在想要像使用RestTemplate时借助MockRestServiceServer那样,Mock GraphServiceClient来返回预设的用户对象进行测试。原方法代码如下:
public User createUser(User user) throws ClientException { final ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder() .clientId(clientId) .clientSecret(clientSecret) .tenantId(tenantId) .build(); final TokenCredentialAuthProvider tokenCredentialAuthProvider = new TokenCredentialAuthProvider(Arrays.asList(scope), clientSecretCredential); GraphServiceClient graphClient = GraphServiceClient.builder() .authenticationProvider(tokenCredentialAuthProvider) .buildClient(); user.passwordPolicies = "DisablePasswordExpiration"; // optional PasswordProfile passwordProfile = new PasswordProfile(); passwordProfile.forceChangePasswordNextSignIn = true; // false if the user does not need to change password passwordProfile.password = "xWwvJ]6NMw+bWH-d"; user.passwordProfile = passwordProfile; return graphClient.users() .buildRequest() .post(user); }
解决方案
1. 重构代码,依赖注入GraphServiceClient
原方法直接在内部创建GraphServiceClient,无法直接Mock。需要将GraphServiceClient的创建逻辑抽离,通过依赖注入的方式传入类中:
重构后的业务类
import com.microsoft.graph.models.User; import com.microsoft.graph.requests.GraphServiceClient; import com.microsoft.graph.http.ClientException; public class UserService { private final GraphServiceClient graphServiceClient; // 通过构造函数注入GraphServiceClient public UserService(GraphServiceClient graphServiceClient) { this.graphServiceClient = graphServiceClient; } public User createUser(User user) throws ClientException { user.passwordPolicies = "DisablePasswordExpiration"; PasswordProfile passwordProfile = new PasswordProfile(); passwordProfile.forceChangePasswordNextSignIn = true; passwordProfile.password = "xWwvJ]6NMw+bWH-d"; user.passwordProfile = passwordProfile; return graphServiceClient.users() .buildRequest() .post(user); } }
配置类(Spring环境下)
将GraphServiceClient注册为Bean,供业务类注入:
import com.azure.identity.ClientSecretCredential; import com.azure.identity.ClientSecretCredentialBuilder; import com.microsoft.graph.authentication.TokenCredentialAuthProvider; import com.microsoft.graph.requests.GraphServiceClient; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Arrays; @Configuration public class GraphClientConfig { @Value("${azure.client-id}") private String clientId; @Value("${azure.client-secret}") private String clientSecret; @Value("${azure.tenant-id}") private String tenantId; @Value("${graph.scope}") private String scope; @Bean public GraphServiceClient graphServiceClient() { ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder() .clientId(clientId) .clientSecret(clientSecret) .tenantId(tenantId) .build(); TokenCredentialAuthProvider authProvider = new TokenCredentialAuthProvider(Arrays.asList(scope), clientSecretCredential); return GraphServiceClient.builder() .authenticationProvider(authProvider) .buildClient(); } }
2. 使用Mockito编写Mock测试
通过Mockito MockGraphServiceClient及其链式调用的对象,预设调用行为:
import com.microsoft.graph.models.User; import com.microsoft.graph.requests.GraphServiceClient; import com.microsoft.graph.requests.UserRequest; import com.microsoft.graph.requests.UserRequestBuilder; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.*; @ExtendWith(MockitoExtension.class) public class UserServiceTest { @Mock private GraphServiceClient graphServiceClient; @Mock private UserRequestBuilder userRequestBuilder; @Mock private UserRequest userRequest; @InjectMocks private UserService userService; @Test void createUser_ShouldReturnMockUser() throws Exception { // 1. 构建预设的请求参数和返回对象 User inputUser = new User(); inputUser.displayName = "Test User"; inputUser.userPrincipalName = "test@example.com"; User mockResponseUser = new User(); mockResponseUser.id = "mock-user-id-123"; mockResponseUser.displayName = "Test User"; // 2. 设定Mock的链式调用行为 when(graphServiceClient.users()).thenReturn(userRequestBuilder); when(userRequestBuilder.buildRequest()).thenReturn(userRequest); when(userRequest.post(inputUser)).thenReturn(mockResponseUser); // 3. 调用业务方法 User result = userService.createUser(inputUser); // 4. 断言结果 assertNotNull(result); assertEquals("mock-user-id-123", result.id); assertEquals("Test User", result.displayName); // 验证调用次数 verify(graphServiceClient, times(1)).users(); verify(userRequestBuilder, times(1)).buildRequest(); verify(userRequest, times(1)).post(inputUser); } }
关键说明
- 由于
GraphServiceClient的调用是链式的(users()->buildRequest()->post()),需要依次Mock每个环节的对象(UserRequestBuilder、UserRequest) - 重构后通过依赖注入解耦了
GraphServiceClient的创建与业务逻辑,让测试可以轻松替换为Mock对象 - 测试中可以完全模拟Graph API的返回结果,无需依赖真实的Azure环境
内容的提问来源于stack exchange,提问作者Aldo Inácio da Silva
相关产品推荐
相关产品推荐

