Rhino Mocks and System.NotSupportedException

84 views
Skip to first unread message

Øyvind

unread,
Feb 11, 2008, 6:25:27 AM2/11/08
to Rhino.Mocks
Hello!

I've just started playing with Rhino Mocks and I have stumbled across
an issue that I was hoping you would be able to help me shed some
light on. Although I have been doing TDD for a while now I am new to
mocking and as such I am not sure if I am going about the tests in the
right way.

I wish to create a mock for a ProfileDao class (data access layer
class for user profiles). ProfileDao inherits from BaseSqlMapDao.
Creating the mock instance is not a problem, however when I set up an
expectation on the mock, an exception is thrown from BaseSqlMapDao
(System.NotSupportedException : The invoked member is not supported in
a dynamic assembly).

I've debugged my test and stepped through to find out what's going on,
and the cause of the exception is a method call on the BaseSqlMapDao
class to load an embedded resource. The exception I'm setting up is
that the ProfileDao mock should call the InsertProfile method with a
specific parameter (and a specific return). On the real ProfileDao
class this call to InsertProfile makes use of a property on
BaseSqlMapDao which, in turn, makes a call to load the embedded
resource (if it has not already been loaded). That is the cause of the
problem.

So in short, the call to load the embedded resource fails because the
call happens within a dynamic assembly (created by Rhino Mocks, I
assume). What I simply don't understand is why the call happens in the
first place. Isn't the mock supposed to intercept my call? I've
included the test source code below in case that helps to clarify what
I'm doing.

Chances are that I am being stupid and not setting up things right -
I'm still getting to grips with the concepts of mocking.

I have included some source code below in case that is helpful to
explain the problem. Any input you may have on this would be most
welcome and appreciated.


--- The Test ---

[Test]
public void TestCreateWithMock()
{

MockRepository mocks = new MockRepository();
Profile profile = new Profile();
Guid newId, returnedId;

returnedId = Guid.NewGuid();
ProfileDao profileDao = (ProfileDao) mocks.CreateMock(typeof
(ProfileDao), new object[] {"", ""});
Expect.Call(profileDao.InsertProfile(profile)).Return(returnedId);

mocks.ReplayAll();
newId = profileDao.InsertProfile(profile);

Assert.AreEqual(newId, returnedId);
Assert.AreEqual(returnedId, profile.Id);
mocks.VerifyAll();
}


--- ProfileDao.InsertProfile(Profile profile) ---

public Guid InsertProfile(Profile profile)
{
Guid newId = Guid.NewGuid();
profile.Id = newId;
ExecuteInsert("InsertProfile", profile);

return newId;
}

--- BaseSqlMapDao.ExecuteInsert and properties ---

protected object ExecuteInsert(string statementName, Object
parameterObject)
{
try
{
return SqlMap.Insert(statementName, parameterObject);
}
catch(SqlException ex)
{
throw CustomException.MapTo(ex);
}
}

protected ISqlMapper SqlMap
{
get
{
if (_sqlMap == null)
_sqlMap = GetLocalSqlMap();

return _sqlMap;
}
}

protected ISqlMapper GetLocalSqlMap()
{
Stream resourceStream =
this.GetType().Assembly.GetManifestResourceStream(_profileResourceString);
DomSqlMapBuilder builder = new DomSqlMapBuilder();
ISqlMapper mapper = builder.Configure(resourceStream);
mapper.DataSource.ConnectionString = _connectionString;

return mapper;
}

Fabian Schmied

unread,
Feb 11, 2008, 7:18:36 AM2/11/08
to Rhino...@googlegroups.com
> What I simply don't understand is why the call happens in the
> first place. Isn't the mock supposed to intercept my call? I've
> included the test source code below in case that helps to clarify what
> I'm doing.

RhinoMocks uses subclassing and thus can only intercept virtual
methods; so you need a virtual (or interface) method in order to set
up an expectation. In your example, InsertProfile is not virtual,
which is why its actual implementation is executed instead of an
expectation being created.

Regards,
Fabian

Øyvind

unread,
Feb 11, 2008, 7:52:54 AM2/11/08
to Rhino.Mocks
Hello!

Thanks for the explanation. Now at least I understand what's going on!

As an aside, isn't this a bit restrictive on part of Rhino Mock?
Limiting testable methods to interface methods or virtual methods
imposes restrictions on how the testable code is written, no?

Regards,
Øyvind




On Feb 11, 12:18 pm, "Fabian Schmied" <fabian.schm...@gmail.com>
wrote:

Stefan Simroth

unread,
Feb 11, 2008, 8:03:46 AM2/11/08
to Rhino...@googlegroups.com

> As an aside, isn't this a bit restrictive on part of Rhino Mock?
> Limiting testable methods to interface methods or virtual methods
> imposes restrictions on how the testable code is written, no?
>

I think that not Rhino.Mocks put that restriction, but the
Castel.DynamicProxy library and their mechanism on how to intercept method
calls. Afaik, it's generally only possible to incept virtual or interface
method calls apart from how Castle DynamicProxy (and so Rhino.Mocks) is
handling this.. right?

Greetings,
Stefan


--
ifu Hamburg - material flows and software

ifu Institut fuer Umweltinformatik Hamburg GmbH
Grosse Bergstrasse 219, 22767 Hamburg, Germany
Managing Director: Jan Hedemann, Commercial Register: Hamburg, HRB 52629
www.ifu.com - www.umberto.de - www.sabento.com - www.e-sankey.com

>>> e!Sankey - Our new software for the easy drawing of Sankey diagrams.
>>> Visit http://www.e-sankey.com

jasonm...@gmail.com

unread,
Feb 11, 2008, 9:25:22 AM2/11/08
to Rhino.Mocks
I believe the term is "design for testability". there ar a number of
article on the subject. It's not so much restrictive as it is a change
in how you write code. My understanding of Rhino is that it creates a
proxy class for the mocked object. therefore it can only mock
(override) calls to abstract/virtual functions and interfaces.

Fabian Schmied

unread,
Feb 11, 2008, 11:35:47 AM2/11/08
to Rhino...@googlegroups.com
> As an aside, isn't this a bit restrictive on part of Rhino Mock?
> Limiting testable methods to interface methods or virtual methods
> imposes restrictions on how the testable code is written, no?

With .NET, there are a few kinds of interception available:

- Remoting proxies
- (Runtime) subclassing
- Static IL or source code rewriting on disk/compiler support
- Profiling API

Each of those has their own set of restrictions, there is no solution
that always works without any constraints or inconveniences. Ayende
probably chose runtime subclassing (via DynamicProxy) very
deliberately. In practice, the virtualness/interface restrictions are
usually not that problematic - in fact, there are quite a few people
advocating that design that can't be mocked that way isn't actually
good design :)

Fabian

Øyvind

unread,
Feb 11, 2008, 11:37:18 AM2/11/08
to Rhino.Mocks
Yes, I believe in writing testable code. But I'm not convinced that
"design for usability" should dictate that all public methods should
be virtual or belong to an interface. Though, as stated by Stefan
(above), this is not by Rhino Mocks' design it is a littlebit silly
that you cannot mock a normal public method. However, armed with this
knowledge I can now of course write code that _is_ testable with Rhino
Mocks.



On Feb 11, 2:25 pm, "jasonmeck...@gmail.com" <jasonmeck...@gmail.com>
wrote:

Ayende Rahien

unread,
Feb 11, 2008, 12:31:56 PM2/11/08
to Rhino...@googlegroups.com
Indeed.
In fact, Rhino Mocks uses two approaches, Remoting proxies and Runtime Subclassing.
If you inherit from MarshalByRefObject, it will use the remoting proxy instead.
Reply all
Reply to author
Forward
0 new messages