I just started writing some tests for a new project and encountered the following "problem":
I mocked the dependent INotifyVariableChangedService and OpcClient to test my 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();
}
Here you can see, that i get the _symbolicsIndex, which i only have to do one time. Consequently i’m persisting it in a field and reusing it whenever i need it again.
This brought up a problem when testing a method like this one, because it depends on the value in this field:
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);
}
Of course i could refactor this and get the _symbolicsIndex everytime in my controller, but that does not seem like a clean solution at all.
Is there a way to "mock" this field ? Should i even be doing that at all or should i refactor it and expose a method, which sets the _symbolicsIndex in my service explicitly, instead of setting it in the constructor ?
Any help would be greatly appreciated.
>Solution :
I don’t think you can mock a private field without using reflection, but I would suggest that you also have the client injected rather than instantiating it in the constructor.
You said the client is already a mocked object, so you could fake the GetSymbolicsNameSpaceId() method and return the desired mocked value, which is then set to the private field when the client is passed to the constructor.
This could then look something like this (assumed FakeItEasy as the mocking libary)
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();
}
Test:
_notifyVariableChangedService = A.Fake<INotifyVariableChangedService>();
_client = A.Fake<OpcUaClient>();
A.CallTo(() => _client.GetSymbolicsNameSpaceId()).Returns(1);
_testee = new OpcService(_notifyVariableChangedService, _client);