如何对依赖于私有字段的方法进行单元测试?

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

我刚开始为一个新项目写一些测试,遇到了以下“问题”:

我嘲笑依赖

INotifyVariableChangedService
OpcClient
来测试我的
OpcService

private readonly OpcUaClient _client;
        private readonly INotifyVariableChangedService _notifyVariableChangedService;
        private readonly ushort _symbolicsIndex;

        public OpcService(INotifyVariableChangedService notifyVariableChangedService)
        {
            this._notifyVariableChangedService = notifyVariableChangedService;

            this._client = new OpcUaClient("", "");

            _symbolicsIndex = _client.GetSymbolicsNameSpaceId();
        }

在这里你可以看到,我得到了

_symbolicsIndex
,我只需要做一次。因此,我将它坚持在一个领域并在我再次需要它时重复使用它。

这在测试这种方法时出现了一个问题,因为它取决于该字段中的值:

public async Task<KeyValuePair<string, object>> GetVariableValue(string nodeIdentifier, string variableName)
        {
            var variableValue = await this._client.GetValue(nodeIdentifier, variableName, _symbolicsIndex);

            return new KeyValuePair<string, object>(variableName, variableValue.Value);
        }

当然我可以重构它并在我的控制器中每次都获得

_symbolicsIndex
,但这似乎根本不是一个干净的解决方案。

有没有办法“模拟”这个领域?我什至应该这样做还是应该重构它并公开一个方法,该方法显式地在我的服务中设置

_symbolicsIndex
,而不是在构造函数中设置它?

任何帮助将不胜感激。

c# unit-testing wcf xunit
1个回答
0
投票

我不认为你可以在不使用反射的情况下模拟私有字段,但我建议你也注入客户端而不是在构造函数中实例化它。

你说客户端已经是一个模拟对象,所以你可以伪造

GetSymbolicsNameSpaceId()
方法并返回所需的模拟值,然后在将客户端传递给构造函数时将其设置为私有字段。

这可能看起来像这样(假设 FakeItEasy 作为模拟库)

private readonly OpcUaClient _client;
private readonly INotifyVariableChangedService _notifyVariableChangedService;
private readonly ushort _symbolicsIndex;

public OpcService(INotifyVariableChangedService notifyVariableChangedService, OpcUaClient client)
{
    this._notifyVariableChangedService = notifyVariableChangedService;
    this._client = client;

    _symbolicsIndex = _client.GetSymbolicsNameSpaceId();
}

测试:

_notifyVariableChangedService = A.Fake<INotifyVariableChangedService>();
_client = A.Fake<OpcUaClient>();

A.CallTo(() => _client.GetSymbolicsNameSpaceId()).Returns(1);

_testee = new OpcService(_notifyVariableChangedService, _client);
© www.soinside.com 2019 - 2024. All rights reserved.