如何对使用NuGet包的类库方法开展测试?
MyService类方法的测试方案
一、测试类型选择
- 优先单元测试:这两个方法的核心是与外部依赖(MyClient、配置、MyAccountsRepository)的交互,单元测试可通过Mock隔离这些外部组件,快速验证自身逻辑的正确性,执行效率高,能覆盖大部分场景。
- 辅助集成测试:如果需要验证端到端流程(比如和真实授权服务、数据库交互),可补充少量集成测试,但不用覆盖所有场景,单元测试才是主力。
二、各方法的测试内容与用例
1. AuthorizationLogin方法
测试覆盖点:
- 确认方法确实调用了MyClient的BuildUri方法,且直接返回该方法的结果,无额外篡改逻辑。
单元测试示例(基于xUnit + Moq框架):
using Moq; using Xunit; public class MyServiceTests { private readonly Mock<IMyClient> _mockMyClient; private readonly MyService _myService; public MyServiceTests() { _mockMyClient = new Mock<IMyClient>(); // 假设MyService通过构造函数注入依赖 _myService = new MyService( _mockMyClient.Object, Mock.Of<IConfiguration>(), Mock.Of<IMyAccountsRepository>() ); } [Fact] public void AuthorizationLogin_ReturnsExactUriFromMyClient() { // 准备测试数据 var expectedAuthUri = "https://auth.example.com/authorize?client_id=test&scope=read"; _mockMyClient.Setup(client => client.BuildUri()).Returns(expectedAuthUri); // 执行方法 var resultUri = _myService.AuthorizationLogin(); // 验证结果 Assert.Equal(expectedAuthUri, resultUri); // 确保BuildUri仅被调用一次 _mockMyClient.Verify(client => client.BuildUri(), Times.Once); } }
2. ExchangeCodeForToken方法
测试覆盖点:
- 确认方法正确传入code参数调用MyClient的RequestTokenAsync
- 确认方法从配置中正确读取MyClient:Scopes的值
- 确认方法用返回的令牌和配置的Scope构造MyAccounts对象,并调用Repository的AddAccount方法
- 异常场景:当MyClient请求令牌抛出异常时,方法是否正确传递异常(无特殊捕获逻辑的情况下)
单元测试示例:
[Fact] public async Task ExchangeCodeForToken_ValidCode_AddsCorrectAccountToRepository() { // 准备测试数据 var testCode = "auth-code-abc123"; var mockToken = new TokenResponse { AccessToken = "test-access-token", RefreshToken = "test-refresh-token" }; var testScopes = "read write profile"; // Mock配置 var mockConfig = new Mock<IConfiguration>(); mockConfig.Setup(config => config["MyClient:Scopes"]).Returns(testScopes); // MockMyClient的请求令牌方法 _mockMyClient.Setup(client => client.RequestTokenAsync(testCode)) .ReturnsAsync(mockToken); // Mock账户仓库 var mockAccountRepo = new Mock<IMyAccountsRepository>(); var myService = new MyService( _mockMyClient.Object, mockConfig.Object, mockAccountRepo.Object ); // 执行方法 await myService.ExchangeCodeForToken(testCode); // 验证调用 _mockMyClient.Verify(client => client.RequestTokenAsync(testCode), Times.Once); // 验证账户对象属性正确且被添加到仓库 mockAccountRepo.Verify(repo => repo.AddAccount(It.Is<MyAccounts>(account => account.AccessToken == mockToken.AccessToken && account.RefreshToken == mockToken.RefreshToken && account.Scopes == testScopes )), Times.Once); } [Fact] public async Task ExchangeCodeForToken_TokenRequestFails_PropagatesException() { // 准备测试数据 var testCode = "invalid-code"; var requestException = new HttpRequestException("Failed to fetch token: invalid grant"); _mockMyClient.Setup(client => client.RequestTokenAsync(testCode)) .ThrowsAsync(requestException); var myService = new MyService( _mockMyClient.Object, Mock.Of<IConfiguration>(), Mock.Of<IMyAccountsRepository>() ); // 验证异常被正确抛出 var thrownException = await Assert.ThrowsAsync<HttpRequestException>( () => myService.ExchangeCodeForToken(testCode) ); Assert.Equal(requestException.Message, thrownException.Message); }
三、集成测试补充(可选)
如果要做集成测试,需要:
- 使用真实的MyClient实例,配置测试环境的OAuth参数(比如测试用client_id、授权地址)
- 使用内存数据库或测试专用数据库作为MyAccountsRepository的实现
- 测试流程:调用AuthorizationLogin拿到授权地址,模拟授权获取code,再调用ExchangeCodeForToken,最后验证数据库中是否正确存储了账户信息
内容的提问来源于stack exchange,提问作者Liam Kenny
相关产品推荐
相关产品推荐

