What is the just mock equivalent of setting the value of a private member variable?
public class foo
{
private IEventAggregator _ea;
...
}
I just want to do something like this:
foo mockedFoo = Mock.Create<foo>();
IEventAggregator fakeEA = Mock.Create<IEventAggregator>();
Mock.NonPublic.Arrange(foo, "_ea", fakeEA);
But this is not working for me and gives me an error:
System.ArgumentException: Could not resolve the target method; make sure that you have provided arguments correctly.
public class foo
{
private IEventAggregator _ea;
...
}
I just want to do something like this:
foo mockedFoo = Mock.Create<foo>();
IEventAggregator fakeEA = Mock.Create<IEventAggregator>();
Mock.NonPublic.Arrange(foo, "_ea", fakeEA);
But this is not working for me and gives me an error:
System.ArgumentException: Could not resolve the target method; make sure that you have provided arguments correctly.
7 Answers, 1 is accepted
0
Hi Jiti,
Thank you for contacting Telerik support.
In order to fake the returning value of a non-public property/member, you will have to arrange against it`s "get" function.
Let`s assume we have the following class with it`s private members:
There are couple of examples that I have prepared about your issue:
I hope this solves your issue. If I can help you with anything else, please do not hesitate to ask.
Regards,
Kaloyan
the Telerik team
Thank you for contacting Telerik support.
In order to fake the returning value of a non-public property/member, you will have to arrange against it`s "get" function.
Let`s assume we have the following class with it`s private members:
public
interface
IEventAggregator
{
string
firstProp {
get
;
set
; }
int
secondProp {
get
;
set
; }
}
public
class
Foo
{
private
IEventAggregator myInterfaceWithSet {
get
;
set
; }
private
string
myStringWithGet {
get
;
set
; }
public
string
ReturningMyInterface()
{
return
myInterfaceWithSet.firstProp;
}
public
string
ReturningMyString()
{
return
myStringWithGet;
}
}
There are couple of examples that I have prepared about your issue:
- We will fake the string property:
[TestMethod]
public
void
ShouldReturnFakeStringWithGetFunction()
{
var mockedFoo = Mock.Create<Foo>(Behavior.CallOriginal);
string
expected =
"telerik"
;
//arrange
Mock.NonPublic.Arrange<
string
>(mockedFoo,
"myStringWithGet"
).Returns(expected);
//act
string
actual = mockedFoo.ReturningMyString();
//assert
Assert.AreEqual(expected, actual);
}
- Faking an interface private member is almost the same. The only difference here is that we need to create a mocked instance of our class/interface with the wanted parameters:
[TestMethod]
public
void
ShouldMockPrivatePropertyWithGetFunction()
{
var mockedFoo = Mock.Create<Foo>(Behavior.CallOriginal);
var mockedIEA = Mock.Create<IEventAggregator>();
mockedIEA.firstProp =
"telerik"
;
mockedIEA.secondProp = 55;
//arrange
Mock.NonPublic.Arrange<IEventAggregator>(mockedFoo,
"myInterfaceWithSet"
).Returns(mockedIEA);
//act
string
actual = mockedFoo.ReturningMyInterface();
//assert
Assert.AreEqual(
"telerik"
, actual);
}
I hope this solves your issue. If I can help you with anything else, please do not hesitate to ask.
Regards,
Kaloyan
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
0
Jiti
Top achievements
Rank 1
answered on 23 Oct 2012, 05:31 PM
Thank you for your reply.
It does work when there is a property or function that sets the member variable. But my production code does not need a setter, it gets set in the constructor. Writing a setter just so that the member variable can be mocked did not seem right. That was why I was wondering if it was possible to set the value of the member variable directly.
For e.g. if I do this,
var realFoo = new foo();
PrivateObject po = new PrivateObject(realFoo);
po.SetField("_ea", fakeEA); // This works (But I need to used a mocked version of foo so in that case po.SetField does not work)
Is there something similar to the above SetField method in JustMock or is it only possible if there is a setter or a method that sets its value, like in the solution proposed?
Thanks,
Jiti
It does work when there is a property or function that sets the member variable. But my production code does not need a setter, it gets set in the constructor. Writing a setter just so that the member variable can be mocked did not seem right. That was why I was wondering if it was possible to set the value of the member variable directly.
For e.g. if I do this,
var realFoo = new foo();
PrivateObject po = new PrivateObject(realFoo);
po.SetField("_ea", fakeEA); // This works (But I need to used a mocked version of foo so in that case po.SetField does not work)
Is there something similar to the above SetField method in JustMock or is it only possible if there is a setter or a method that sets its value, like in the solution proposed?
Thanks,
Jiti
0
Jiti
Top achievements
Rank 1
answered on 23 Oct 2012, 09:35 PM
I just checked and looks like just having a private setter does not work. It needs to be a private method that takes an argument.
So if the production code had the property
private IEventAggregator EventAggregator { get; set; }
then in the test case,
Mock.NonPublic.Arrange(foo, "EventAggregator", fakeEA);
does not work!
But if the production code had the method
private void SetEventAggregator(IEventAggregator ea)
{
_ea = ea;
}
then in the test case,
Mock.NonPublic.Arrange(foo, "SetEventAggregator", fakeEA);
works!
I wonder why it does not work with private property.
Thanks,
Jiti
So if the production code had the property
private IEventAggregator EventAggregator { get; set; }
then in the test case,
Mock.NonPublic.Arrange(foo, "EventAggregator", fakeEA);
does not work!
But if the production code had the method
private void SetEventAggregator(IEventAggregator ea)
{
_ea = ea;
}
then in the test case,
Mock.NonPublic.Arrange(foo, "SetEventAggregator", fakeEA);
works!
I wonder why it does not work with private property.
Thanks,
Jiti
0
Hi Jiti,
Thank you for coming back to us.
As I can understand from your first reply, you are trying to fake datum. Unfortunately this is not possible in JustMock, neither in other mocking tools. What our product is expected to do is to fake an object by mocking its behavior.
For example: You create a fake class, so that you can comfortably arrange the new behavior of its functionality, or methods.
However, as I noted above, mocking or faking datum is not directly allowed. Nevertheless, there are ways and principles in programming that can permit you, fake the value of a certain variable. One of them, I would recommend, is the using of a property, that is acting directly with your private member variable. Having such, you can easily mock its get or set function, so that it returns or takes a certain data.
Let`s assume you are having this "SomeClass" class.
As you can see there is a member variable "_myProperty", that is taking its value inside the constructor. The mandatory here is that, we have a property "MyProperty", that can show or change the variable`s value. From now on, it is good to use 'MyProperty', instead of "_myProperty", to cover the rest of "SomeClass" functional logic. If we continue to the testing part, you will notice that, now it is very easy to fake the whole behavior of our class:
As for your second concern, I must say that you are right. Having a private setter won`t let you fake the returning value. You will need a private property with both get and set functions, or atleast with a getter, so that you can arrange that function to return the desired value, the same way, as you are arranging methods for example:
Note that, you will need to specify the property type ("<IEventAggregator>") first. Then you have to point the previously mocked class/interface ("foo") with its property/method you would like to arrange against ("EventAggregator"). Finally you need to fake its get function, so that it returns your "fakeEA", instead of the original value (".Returns(fakeEA)").
I hope you will find this information useful and it will lead you to solving you issue. Please, let me know if I can be helpful with anything else.
Regards,
Kaloyan
the Telerik team
Thank you for coming back to us.
As I can understand from your first reply, you are trying to fake datum. Unfortunately this is not possible in JustMock, neither in other mocking tools. What our product is expected to do is to fake an object by mocking its behavior.
For example: You create a fake class, so that you can comfortably arrange the new behavior of its functionality, or methods.
However, as I noted above, mocking or faking datum is not directly allowed. Nevertheless, there are ways and principles in programming that can permit you, fake the value of a certain variable. One of them, I would recommend, is the using of a property, that is acting directly with your private member variable. Having such, you can easily mock its get or set function, so that it returns or takes a certain data.
Let`s assume you are having this "SomeClass" class.
class
SomeClass
{
public
SomeClass()
{
_myProperty = 123;
}
public
int
_myProperty;
public
int
MyProperty
{
get
{
return
this
._myProperty; }
set
{
this
._myProperty = value; }
}
}
[TestMethod]
public
void
TestMethod1()
{
var mock = Mock.Create<SomeClass>();
// Arrange
Mock.Arrange(() => mock.MyProperty).Returns(321);
// Act
var actualValue = mock.MyProperty;
var origValue = mock._myProperty;
// Assert
Assert.AreNotEqual(actualValue, origValue);
Assert.AreEqual(321, actualValue);
Assert.AreEqual(123, origValue);
}
As for your second concern, I must say that you are right. Having a private setter won`t let you fake the returning value. You will need a private property with both get and set functions, or atleast with a getter, so that you can arrange that function to return the desired value, the same way, as you are arranging methods for example:
Mock.NonPublic.Arrange<IEventAggregator>(foo,
"EventAggregator"
).Returns(fakeEA);
I hope you will find this information useful and it will lead you to solving you issue. Please, let me know if I can be helpful with anything else.
Regards,
Kaloyan
the Telerik team
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.
0
Chuck
Top achievements
Rank 1
answered on 01 Feb 2013, 09:26 PM
I'd like to follow up on this, which seems to me a major failing (inability to mock a private member variable). Consider the following
public class TM
{
private Task m_ActiveTask = null;
// provide readonly access to the world
public Task ActiveTask
{
get { return m_ActiveTask;}
}
// let users set the Active task, which is a complicated operation, NOT just an assignment to internal variable
public void SetActiveTask (string sTaskName)
{
// lots of complicated manipulations, including
Task oNewTask = new Task(...);
//finally resulting in
m_ActiveTask = oNewTask;
}
// later, another function may need to test whether any task is active
public void Cleanup()
{
if(null != m_ActiveTask)
{
// do some cleanup, then
m_ActiveTask = null;
}
}
}
Now, I want to write a unit test for Cleanup. Obviously, I need to put a Mocked Task object in m_ActiveTask. But it is a private member variable.
Obviously, I do not want to expose it as public. I have good and sound reasons for maintaining within TM the ability to SET the variable, and not to allow the casual caller to mess with it.
How does one proceed in this situation?
Let's assume JustMock JustWon't allow me to set the member variable directly (see how I JustMade that little joke? :), and that I'm willing to refactor my code so that class methods always access via the property, thus:
public void Cleanup()
{
if(null != ActiveTask) // use property
{
// do some cleanup, then
m_ActiveTask = null;
}
}
If I then define my property THIS way, is there some way to get it JustRight?
public Task ActiveTask
{
get { return m_ActiveTask; }
private set { m_ActiveTask = value; } // make setter private to the class
}
Thanks.
(btw, Jiti, is a co-worked of mine, and we are working on different parts of the same product)
public class TM
{
private Task m_ActiveTask = null;
// provide readonly access to the world
public Task ActiveTask
{
get { return m_ActiveTask;}
}
// let users set the Active task, which is a complicated operation, NOT just an assignment to internal variable
public void SetActiveTask (string sTaskName)
{
// lots of complicated manipulations, including
Task oNewTask = new Task(...);
//finally resulting in
m_ActiveTask = oNewTask;
}
// later, another function may need to test whether any task is active
public void Cleanup()
{
if(null != m_ActiveTask)
{
// do some cleanup, then
m_ActiveTask = null;
}
}
}
Now, I want to write a unit test for Cleanup. Obviously, I need to put a Mocked Task object in m_ActiveTask. But it is a private member variable.
Obviously, I do not want to expose it as public. I have good and sound reasons for maintaining within TM the ability to SET the variable, and not to allow the casual caller to mess with it.
How does one proceed in this situation?
Let's assume JustMock JustWon't allow me to set the member variable directly (see how I JustMade that little joke? :), and that I'm willing to refactor my code so that class methods always access via the property, thus:
public void Cleanup()
{
if(null != ActiveTask) // use property
{
// do some cleanup, then
m_ActiveTask = null;
}
}
If I then define my property THIS way, is there some way to get it JustRight?
public Task ActiveTask
{
get { return m_ActiveTask; }
private set { m_ActiveTask = value; } // make setter private to the class
}
Thanks.
(btw, Jiti, is a co-worked of mine, and we are working on different parts of the same product)
0
Chuck
Top achievements
Rank 1
answered on 01 Feb 2013, 09:46 PM
Nevermind.
If I'm willing to refactor to use the property in the TM class, of course I can sufficiently mock a .Returns on the property.
I still believe the ability to set private member variables will be sine qua non for comprehensive test coverage. There will be times when the state of private member variables that are PURELY private, and need NO exposure, will determine code path execution. Requiring the programmer to make them private *properties* rather than member variables is just silly.
If I'm willing to refactor to use the property in the TM class, of course I can sufficiently mock a .Returns on the property.
I still believe the ability to set private member variables will be sine qua non for comprehensive test coverage. There will be times when the state of private member variables that are PURELY private, and need NO exposure, will determine code path execution. Requiring the programmer to make them private *properties* rather than member variables is just silly.
0
Hello Chuck,
Thank you for the detailed feedback.
You are correct that such feature will definitely enrich JustMock.
I would suggest you using our Ideas and Feedback portal, so that other clients could also vote for its implementation in our product.
Kind regards,
Kaloyan
the Telerik team
Thank you for the detailed feedback.
You are correct that such feature will definitely enrich JustMock.
I would suggest you using our Ideas and Feedback portal, so that other clients could also vote for its implementation in our product.
Kind regards,
Kaloyan
the Telerik team