Blazor 的模拟 ProtectedSessionStorage

问题描述 投票:0回答:2

有没有办法在 Blazor 服务器端项目中模拟 ProtectedSessionStorage?

我尝试了下面的代码,但收到错误:“要模拟的类型 (ProtectedSessionStorage) 必须是接口、委托或非密封、非静态类。”

private readonly Mock<ProtectedSessionStorage> _sessionStorage = new();
private readonly Mock<IDataProtector> _mockDataProtector = new();
private readonly Mock<IDataProtectionProvider> _mockDataProtectionProvider = new();


//in ctor()
Services.AddSingleton(_sessionStorage.Object);

//mock IDataProtector
_mockDataProtector = new Mock<IDataProtector>();
_mockDataProtector.Setup(sut => sut.Protect(It.IsAny<byte[]>())).Returns(Encoding.UTF8.GetBytes("protectedText"));
_mockDataProtector.Setup(sut => sut.Unprotect(It.IsAny<byte[]>())).Returns(Encoding.UTF8.GetBytes("originalText"));
Services.AddSingleton(_mockDataProtector.Object);

//mock IDataProtectionProvider
_mockDataProtectionProvider = new Mock<IDataProtectionProvider>();
_mockDataProtectionProvider.Setup(s => s.CreateProtector(It.IsAny<string>())).Returns(_mockDataProtector.Object);
Services.AddSingleton(_mockDataProtectionProvider.Object);


//in testMethod()
EquipmentSearchFilterDto filter = new();
filter.HospitalID = 1;

var result = new ProtectedBrowserStorageResult<EquipmentSearchFilterDto>();

_sessionStorage.Setup(x => x.GetAsync<EquipmentSearchFilterDto>(It.IsAny<string>()))
    .ReturnsAsync(new ProtectedBrowserStorageResult<EquipmentSearchFilterDto>());

我想过将 ProtectedSessionStorage 实现隐藏在接口后面,不幸的是我无法想出一个。有什么想法吗?

moq blazor-server-side xunit bunit
2个回答
6
投票

由于这些类的设计方式,模拟它们并不容易,但我终于做到了。

请注意,要使其正常工作,此代码必须在从 https://bunit.dev/

继承 Bunit.TestContext 的类上运行

TestContext 将允许您使用下面的 this.JSInterop。

    // This string will be the json of the object you want
    // to receive when GetAsync is called from your ProtectedSessionStorage.
    // In my case it was an instance of my UserSession class.
    string userSessionJson = JsonSerializer.Serialize(new UserSession
    {
        EMail = "[email protected]",
        Name = "Test User",
        Role = "TestRole"
    });

    // Base64 used internally on the ProtectedSessionStorage.
    string base64UserSessionJson = Convert.ToBase64String(Encoding.ASCII.GetBytes(userSessionJson));

    // Notice how the mocked methods return the json.
    Mock<IDataProtector> mockDataProtector = new Mock<IDataProtector>();
    _ = mockDataProtector.Setup(sut => sut.Protect(It.IsAny<byte[]>())).Returns(Encoding.UTF8.GetBytes(base64UserSessionJson));
    _ = mockDataProtector.Setup(sut => sut.Unprotect(It.IsAny<byte[]>())).Returns(Encoding.UTF8.GetBytes(userSessionJson));

    Mock<IDataProtectionProvider> mockDataProtectionProvider = new Mock<IDataProtectionProvider>();
    _ = mockDataProtectionProvider.Setup(s => s.CreateProtector(It.IsAny<string>())).Returns(mockDataProtector.Object);

    // This is where the JSInterop by bunit is used.
    // localStorage might need to be changed to your variable name or
    // purpose? If you execute the test without this setup
    // an exception will tell you the name you need to use.
    _ = this.JSInterop.Setup<string>("localStorage.getItem", "UserSession").SetResult(base64UserSessionJson);

    // Use this instance on your constructor or context.
    ProtectedSessionStorage protectedSessionStorage = new ProtectedSessionStorage(
        this.JSInterop.JSRuntime,
        mockDataProtectionProvider.Object);

0
投票

我来得有点晚了,但由于这在谷歌排名中突然出现很高,我想给出一种不同的方法。

(对我来说)最简单、最可持续的方法是将这种行为封装在它自己的不起眼的对象中。在单元测试中,您不想处理第 3 方问题(从代码的角度来看,Blazor/ProtectedStorage 就是其中之一)。

因此你可以有一个像这样的小包装纸:

public sealed class LocalStorageService : ILocalStorageService
{
    private readonly ProtectedLocalStorage localStorage;

    public LocalStorageService(ProtectedLocalStorage localStorage)
    {
        this.localStorage = localStorage;
    }

    public async ValueTask<bool> ContainKeyAsync(string key) => (await localStorage.GetAsync<object>(key)).Success;

    public async ValueTask<T> GetItemAsync<T>(string key) => (await localStorage.GetAsync<T>(key)).Value;

    public async ValueTask SetItemAsync<T>(string key, T value) => await localStorage.SetAsync(key, value);
}

这允许您使用

ILocalStorageService
,它在测试中很容易伪造/模拟。您的测试不涉及任何第三方问题。 即使
ProtectedLocalStorage
(或
ProtectedSessionStorage
)发生变化 - 您也不必在测试中处理这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.