问题
I know a similar question has been asked but I have not found a clear solution. I'm trying to mock a private field from a large class. The private field gets instantiated in some earlier method and I'm trying to unit test a latter method which references the field.
So I have an earlier method in my class:
public bool validateAll(ref DataEntry[] oEntries, string sMediaPlanId, ITemplateGenerator oTempGen)
{
...
// private field that I am trying to mock
this._sMediaPlanObjective = (MPWrapper.Instance).getMediaPlanObjective(sMediaPlanId);
...
}
And I'm trying to Unit test a method that references the private field:
public bool validateFlightObjective(ref MPDataEntry oEntry)
{
...
string entryFlightObjective = oEntry.getFlightObjective();
string mediaPlanObjective = this._sMediaPlanObjective;
if (entryFlightObjective != mediaPlanObjective)
{
return false;
}
...
return true;
}
Given that I have a large class and this is just one method I want to test, is there a possible way to just mock this private field? Am I missing something basic or should I consider some other approach?
回答1:
You can't mock anything that's private, static, or essentially - non overridable (this comes as a free mocking libraries limitation).
What you usually do in such situations (when it appears that private
member has to be tested), is extracting your private
member to a separate class and inject it to tested class as a dependency.
In your case, you actually need to extract code that creates _sMediaPlanObjective
, which is this line:
this._sMediaPlanObjective =
(MPWrapper.Instance).getMediaPlanObjective(sMediaPlanId);
Object that provides getMediaPlanObjective
method should be injected to your tested class. If you do so, you can simply mock that object and tell it to return mocked version of _sMediaPlanObjective
.
回答2:
There is no reason to have any kind of tests on private
fields.
using an object you can reference to the public
methods as the object API.
the object itself can have it's changing state according to the operation you perform on it - but it will be reflected in other public
methods / access to DAL (DB / Registry / File/ any other resource that is not in memory)
So in your case you can have a unit tests like that:
call the method that initializes the private field as you expect it to and -
Call
validateFlightObjective
with a parameter that you know that have to return false according to the_sMediaPlanObjective
"wanted to be state", and verify that the result is false.Call
validateFlightObjective
with a parameter that you know that have to return true according to the_sMediaPlanObjective
"wanted to be state", and verify that the result is true.
If you see that it is hard to test this object, then that might be a "smell" - maybe you have more than one responsibility there and you should start refactoring and split the class to smaller classes which will be easier to test
That it a bit long but i hope it was helpful
回答3:
You can use JustMock framework. For example:
double value = 0;
var fakeFilterSetHelper = Mock.Create<FilterSetHelper>(Behavior.CallOriginal);
Mock.NonPublic.Arrange<double>(fakeFilterSetHelper, memberName: "GetPriceRangeFromSession").Returns(value);
来源:https://stackoverflow.com/questions/11213553/mocking-a-private-field