Mock an internal property in an external assembly

787 views
Skip to first unread message

vanden...@gmail.com

unread,
Mar 22, 2008, 6:14:31 PM3/22/08
to Moq Discussions
Hi,

I'm just started using Moq. I must say I like the way it is setup.
Very elegant.

I'm struggling to set-up an expectation for a property that is marked
as internal. The mocked up class is in an external assembly. This
obviously doesn't work with lambda's approach because the property is
not accessable from the test assembly.

I want to test my class A. Class A derives from class B. Class B is
declared in an external third party assembly. Class B has a
constructor that needs an instance of a 'Session' class as a
parameter. So I am trying to mockup the Session object. During
construction class B calls an internal property called 'IsConnected'
on the Session instance.

Is there a way to get this to work?

Thanks in advance.

Daniel Cazzulino

unread,
Mar 23, 2008, 12:27:11 AM3/23/08
to moq...@googlegroups.com
As a general design principle, "Session" should be an interface, or an abstract base class, so that you can properly abstract it.
If the library/external assembly doesn't allow that, resorting to calling an internal member of the base class, then there's little you can do to make that library more test-friendly.

One way would be invoking some of these internals yourself using reflection.
The mock.Object property will contain an instance of a class that derives from the T you specify for the mock. therefore, if it inherits some behavior, you can still invoke that using reflection, but there's no way to set an expectation on that. And that's by design. You cannot mock internal stuff.

HTH

vanden...@gmail.com

unread,
Mar 23, 2008, 9:58:19 AM3/23/08
to Moq Discussions
Daniel,

Thank you for your quick response. I have found a way to get it to
work. What I did is that I created a nested class in my test class
that inherited from the Session class in the external assembly. In
this class I did hide the inhereted member IsConnected.

public class MySession:Session
{
public new bool IsConnected{ get; set; }
}

Now I can test my class B with:

var l_SessionMock = new Mock<MySession>();
l_SessionMock.Expect(x => x.IsConnected).Returns(false);

String l_expected = "test";
ClassB l_classB = new ClassB(l_SessionMock.Object);
l_classB.Title = l_expected;
Assert.AreEqual(l_classB.Title, l_expected);

Daniel Cazzulino

unread,
Mar 23, 2008, 5:42:33 PM3/23/08
to moq...@googlegroups.com
Clever!

Daniel Cazzulino

unread,
Mar 23, 2008, 5:45:26 PM3/23/08
to moq...@googlegroups.com
Mmmm... does that work as expected? (hitting the mock expectation rather than the base "IsConnected" property?)

If ClassB works with MySession instances, it will work, but if your're passing it as a Session to other code, when they call IsConnected they will be calling the "hidden" version, not yours...

vanden...@gmail.com

unread,
Mar 24, 2008, 12:10:35 PM3/24/08
to Moq Discussions
You might be right. When I set the MockBehavior to MockBehavior.Strict
I get the Moq.MockException: Session.get_IsObjectLoading() invocation
failed with mock behavior Strict. All invocations on the mock must
have a corresponding expectation..

But somehow this scheme works for me. When I don't have the overridden
MySession class I get the System.Runtime.Remoting.RemotingException:
Parameter van het waardetype ByRef kan niet null zijn..
When I look in the callstack I see:
System.Runtime.Remoting.Proxies.RealProxy.ValidateReturnArg(Object
arg, Type paramType)
System.Runtime.Remoting.Proxies.RealProxy.PropagateOutParameters(IMessage
msg, Object[] outArgs, Object returnValue)
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage
reqMsg, IMessage retMsg)
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&
msgData, Int32 type)
SessionProxy09de88bd7bb1442a87e53ef54c3805bf.get_IsConnected()

My objective for setting up an expectation was simulating the
existance of the IsConnected property (and get rid of the exception
listed above) rather than giving back a specified return value. As it
turnes out, I don't need to set up an exspectation, it just works with
the overridden MySession class alone. Maybe this scheme works because
Moq can not see the hidden IsConnected property so it can not mock it
by giving back a default vale, but by redeclaring it in my MySession
class it can. But if this is the case, why does setting up an
expectation does not work?
Reply all
Reply to author
Forward
0 new messages