Let's say I have a class
class MyClass
{
public virtual void MyFunc1( DateTime somedate)
{}
public virtual void MyFunc2( )
{
MyFunc1(SomeObject.SentDate)
}
}
where SomeObject has a field called SentDate.
SomeObject is in a global scope and, for some reasons, I can't provide a value for it so will always be null when mocking.
I can arrange for MyFunc1() to do whatever I want but, when I call MyFunc2(), it will try to evaluate its parameter SomeOject.SentDate and, because SomeObject is null, this will fail with an exception.
Is there a way to skip the evaluation of SomeObject.SentDate parameter?
5 Answers, 1 is accepted
I am not sure what exactly do you mean by "I can't provide a value for it so will always be null when mocking". This said, could you please share the failing unit test related to the above code snippet, so we can investigate for possible issues further? Thanks for this in advance.
Regards,
Kaloyan
Telerik
Hi, here is the complete testing code.
01.
<P>
02.
using
System;
03.
using
Microsoft.VisualStudio.TestTools.UnitTesting;
04.
using
Telerik.JustMock;
05.
using
Telerik.JustMock.Core;
06.
07.
namespace
TestMock1
08.
{
09.
[TestClass]
10.
public
class
UnitTest1
11.
{
12.
[TestMethod]
13.
public
void
TestMethod1()
14.
{
15.
var mock = Mock.Create<MyClass>(Behavior.CallOriginal);
16.
Mock.Arrange(() => mock.MyFunc1(DateTime.Now)).DoNothing();
17.
mock.MyFunc2();
18.
}
19.
}
20.
21.
class
SomeClass
22.
{
23.
public
DateTime SentDate {
get
;
set
; }
24.
}
25.
26.
public
class
MyClass
27.
{
28.
SomeClass SomeObject;
29.
30.
SomeClass GetObjectFromDB()
31.
{
32.
SomeClass obj =
new
SomeClass();
33.
// get it from DB
34.
return
obj;
35.
}
36.
37.
public
virtual
void
MyFunc1(DateTime somedate)
38.
{
39.
SomeObject = GetObjectFromDB();
40.
}
41.
public
virtual
void
MyFunc2()
42.
{
43.
MyFunc1(SomeObject.SentDate);
44.
}
45.
46.
}
47.
}</P>
At line 43 the code produces an exception because SomeObject is null
On a separate note, if I declare MyFunc2() as "internal" instead of "public", I can skip Behavior.CallOriginal and the original code is still called. I am not sure if this is a bug or feature.
In your first question, the code of MyClass seems to be semantically incorrect, because it uses SomeObject before it being assigned. Regardless, there's no way to skip the evaluation of SomeObject.SentDate, if SomeObject is a field. If you just want to test the MyFunc2 method, you can supply a mock for SomeObject, like so:
var mock = Mock.Create<MyClass>(Behavior.CallOriginal);
Mock.Arrange(() => mock.MyFunc1(Arg.IsAny<DateTime>())).DoNothing();
new
PrivateAccessor(mock).SetField(
"SomeObject"
, Mock.Create<SomeClass>());
mock.MyFunc2();
Also, it is not a bug that making MyFunc2 internal prevents it from being mocked. When using JustMock Lite, you can only mock members that are normally accessible for inheritance. To mock internal virtual members, you need to use the InternalsVisibleTo attribute as explained in the documentation.
Regards,
Stefan
Telerik
Thanks for the answer. The first question was what I was looking for and you answered it.
Regarding the second question (actually just a note) I think I was misunderstood. I didn't say internal prevents mocking, by the contrary (sort of). When the function is "virtual public" in order to call the original you have to Create the mock with Behavior.CallOriginal param or to arrange and CallOriginal.
When the same function is declared as "virtual internal" the original is called without any of the above settings.
I'm glad that you got what you came for.
Behavior.CallOriginal was not necessary when the method was internal, because JustMock was not able to override it anyway. When it's public, JustMock is able to override it and mock it out, hence the need for Behavior.CallOriginal.
Regards,
Stefan
Telerik