Mock
在測試中,我們有時候會遇到一些服務是需要遠端資料庫或 API 來取得資訊,但是這樣的服務在測試中會變得很困難,因為我們無法控制遠端服務的狀態,也無法確保遠端服務的可用性。
重點
要模擬的服務需要是介面 (IDomainManager) 而不是實現類 (DomainManager)
實際要測試的方法裡頭,需透過介面 (IDomainManager) 來注入該服務 (DomainManager)
情境
要測試 _appService.GetAsync
方法,而該方法裡頭會使用 DemoManager.GetUser
來呼叫遠端 API 來取得資訊,但該 API 限制只有正式環境可以訪問,所以我需要 MOCK 該方法,而不必實際呼叫該 API。
Mock
Abp 提供了一個簡單的方法來模擬服務,這樣我們就可以在測試中使用模擬的服務,而不是真實的服務。 這樣我們就可以專注於測試我們的代碼,而不是依賴的服務。
protected override void AfterAddApplication(
IServiceCollection services)
{
var mockUser = new DemoUserObject {
Name = DemoConsts.DefaultName,
Ext = DemoConsts.DefaultExt
};
var mockDemoManager = Substitute.For<IDemoManager>();
// Mock GetUserExtAsync 方法
mockDemoManager
.GetUser(Arg.Any<string>())
.Returns(mockUser);
services.AddSingleton(mockDemoManager);
}
使用
Substitute.For<IDemoManager>()
來模擬服務使用
Arg.Any<string>()
來模擬任何字串參數使用
Returns(mockUser)
來模擬該方法的回傳值使用
services.AddSingleton(mockDemoManager)
來注入模擬的服務
Demo
完整範例如下:
using Microsoft.Extensions.DependencyInjection;
using NSubstitute;
using Shouldly;
using Volo.Abp;
using Volo.Abp.Json;
using Volo.Abp.Modularity;
using Xunit;
using Xunit.Abstractions;
namespace Demo;
/* This is just an example test class.
* _testOutputHelper.WriteLine() is used to log the result of the test
*/
public abstract class DemoAppServiceTests<TStartupModule>
: DemoApplicationTestBase<TStartupModule>
where TStartupModule : IAbpModule
{
private readonly IDemoAppService _appService;
private readonly ITestOutputHelper _testOutputHelper;
protected NandPackageAppServiceTests(
ITestOutputHelper testOutputHelper
)
{
_testOutputHelper = testOutputHelper;
_appService = GetRequiredService<IDemoAppService>();
}
protected override void AfterAddApplication(
IServiceCollection services
)
{
var mockUser = new DemoUserObject {
Name = DemoConsts.DefaultName,
Ext = DemoConsts.DefaultExt
};
var mockDemoManager = Substitute.For<IDemoManager>();
// Mock GetUserExtAsync 方法
mockDemoManager
.GetUser(Arg.Any<string>())
.Returns(mockUser);
services.AddSingleton(mockDemoManager);
}
[Fact]
public async Task Should_Get_A_Demo()
{
// Arrange
var req = new GetDemoRequest
{
Demo = NandConsts.TestDemo
};
// Act
var result = await _appService.GetAsync(req);
// Assert
result.ShouldNotBeNull();
result.Name.ShouldBe(NandConsts.DefaultName);
result.Ext.ShouldBe(NandConsts.DefaultExt);
// Log
_testOutputHelper.WriteLine(
GetRequiredService<IJsonSerializer>().Serialize(result));
}
}
Last modified: 20 November 2024