Rhino Mocks and OpenAccess ORM

182 views
Skip to first unread message

jdl

unread,
Sep 12, 2012, 9:25:34 PM9/12/12
to rhino...@googlegroups.com
All,

I have been going back and form with the team at Telerik that put out JustMock as I am evaluating several mocking frameworks right now. I spend most of my day working in business layer logic in IIS hosted WCF services. I am attempting to break my SQL server dependecy in my unit tests by mocking out the db context. A Rhino Mocks users essentially achieved what I am looking for here in 2009 using an old implementation of OpenAccess here: http://www.reversealchemy.net/blog/2009/03/17/exploring-telerik-openaccess-unit-testing-your-business-logic-using-rhino-mocks/. The issue is several fold but the root of it is that OA has fundamentally changed its implementation since then and I cannot seem to get it to jive quite right with either JustMock or not Rhino Mocks. I have emailed the original author of the article to see if he has an updated example and will post his response here should he respond. Ultimately what it boils down to is that I have methods that perform business logic that may or may not add/update entities (hacked example code below). What I am trying to achieve (and it simply may not be possible given my end goal and I apologize as I am relatively new to mocking) is to break the dependency on a DB on the other end while still leveraging the code as if it were (i.e Add an entity to the context but not actually commit it OR when an add occurs on an entity whose ID is a uniqueidentifier (guid), return a new guid to simulate success which allows the update method to use that entity's guid to perform the update operation).

Please let me know if you need a more extensive code example. I am hopeful that Erik's post and the sample methods below will highlight what I am trying to do, something that I have not yet successfully conveyed to Telerik.

public static Guid AddUser(string name, int legacyId = -1)
        {
            try
            {
                using (var model = new VerifyModel())
                {
                    User userEntity = GetUserEntity(name);
 
                    if (userEntity != null)
                    {
                        return userEntity.Guid;
                    }
 
                    var newUser = new User
                    {
                        Name = name,
                        LegacyId = legacyId
                    };
 
                    model.Add(newUser);
                    model.SaveChanges();
                    UserContainer.Instance.Refresh();
                    return newUser.Guid;
                }
            }
            catch (Exception exception)
            {
                ErrorLogWriter.Write(MethodBase.GetCurrentMethod().Name, exception);
            }
 
            return Guid.Empty;
        }
 
Update method handles optimistic verification exceptions but at the end of the day simply performs a sql update.
 
public static bool UpdateUserDetails(Guid userGuid, IEnumerable<ElementAttributeValues> elementAttributeValues)
        {
            try
            {
                var historyEvents = new List<string>();
 
                using (var model = new VerifyModel())
                {
                    var user = model.Users.SingleOrDefault(p => p.Guid == userGuid);
 
                    if (user == null)
                    {
                        return false;
                    }
 
                    var enumeratedElementAttributeValues = elementAttributeValues asList<ElementAttributeValues> ?? elementAttributeValues.ToList();
 
                    try
                    {
                        UpdateUserEntity(enumeratedElementAttributeValues, ref user, refhistoryEvents);
 
                        model.SaveChanges();
                    }
                    catch (OptimisticVerificationException optimisticVerificationException)
                    {
                        ErrorLogWriter.Write(string.Format("An optimistic verification exception occured in {0} and the commit will be retried. The error message is: {1}.",
                                                           MethodBase.GetCurrentMethod().Name,
                                                           optimisticVerificationException.Message));
 
                        model.Refresh(RefreshMode.OverwriteChangesFromStore, user);
 
                        // retry update
                        UpdateUserEntity(enumeratedElementAttributeValues, ref user, refhistoryEvents);
 
                        model.SaveChanges();
                    }
 
                    foreach (string historyEvent in historyEvents)
                    {
                        HistoryWriter.Write(userGuid, historyEvent);
                    }
 
                    return true;
                }
            }
            catch (Exception exception)
            {
                ErrorLogWriter.Write(MethodBase.GetCurrentMethod().Name, exception);
            }
 
            return false;
        }


Patrick Steele

unread,
Sep 13, 2012, 7:53:04 AM9/13/12
to rhino...@googlegroups.com
There's not much to go on here, but a few things I noticed:

1. The methods you showed are static. At some point, you may want to
mock out these methods when testing other parts of your code. Static
methods are not mockable with Rhino.Mocks. You should make the
virtual instance methods.
2. What is the "VerifyModel" you create?
3. If model.Add() and model.SaveChanges() are virtual, you can mock
them, but you'd have to change the way the 'model' is created (inject
it or provide a factory to create it).
4. "UserContainer.Instance.Refresh()" --> looks like another static
method. Those can't be mocked/stubbed with Rhino.Mocks

---
Patrick Steele
http://weblogs.asp.net/psteele
> --
> You received this message because you are subscribed to the Google Groups
> "Rhino.Mocks" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/rhinomocks/-/QqeKVDy-DTkJ.
> To post to this group, send email to rhino...@googlegroups.com.
> To unsubscribe from this group, send email to
> rhinomocks+...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/rhinomocks?hl=en.

jdl

unread,
Sep 14, 2012, 1:40:04 AM9/14/12
to rhino...@googlegroups.com
Patrick,

Thank you for the response.

1) Up until this point, the class that has handled the very transactional work of performing my CRUD operations has not needed to be stateful and is static. If that needs to change in order to achieve what I am after, so be it.

2) VerifyModel, similar to the dbContext of an EF based project is Telerik's database context object which is created with generating their .rlinq designer file (liken it to an EF .edmx file).

3) .Add and .SaveChanges are transactional database workers of OA (along with delete, flushchanges, etc...). I was already considering dependency injecting the ObjectScope in an overloaded constructor so that I could pass in a mocked ObjectScope which would own the transaction over its lifecycle. I am not sure what the behavior would be of mocking the VerifyModel but it is an interesting thought. Have you ever done something similar with the dbcontext of an EF project?

4) Sorry, that like was part of a ConcurrentDictionary caching scheme and should not have made it into my sample.

Thanks,

Jim

bill richards

unread,
Sep 14, 2012, 3:28:45 AM9/14/12
to rhino...@googlegroups.com
Jim,

I'm not 100% clear about where you are considering adding ObjectScope in an overloaded constructor, but I would recommend that you do not do it, this technique/trick has come to be known as "bastard injection" and it is a code smell.

You are on the right track by injecting ObjectScope, but I would seriously recommend NOT overloading the constructor, but rather have a single constructor which is provided with all of the class' dependencies, there are various reasons why you should not use bastard injection if you can avoid it (which generally means if it's a class that you have written or rather, when the code used is not generated by an automaton), the most important of these reasons is that you will most likely be using the class differently under test than you will in released code; which then beggars the question of what your tests are actually testing ... turns out that usually they are testing code put in place specifically to enable testing ... which means that you will get false positives/negatives, you could also find that in your released code you might have some dependency issues since the code has been modified in some "hacky" manner in order to use the injected dependency under test, or to new it up somehow in live.

Using Rhino, you will not be able to mock your CRUD service unless it's members are instance and virtual. In my opinion, the CRUD service should not be static anyhow ... there are other objects that have dependencies upon this static class, make that dependency explicit in your design (i.e. inject an instance of the CRUD service). There are times and places for statics, but most of the time they are not where and when they are being used ... something which I find quite annoying about ReSharper is its constant insistence upon informing one that a member can be made static.

So the points that Patrick has raised are valid, however I'm not entirely sure of what the real issue is that needs attention ... sometimes I'm a bit dim see?
Message has been deleted

bill richards

unread,
Sep 14, 2012, 3:38:45 AM9/14/12
to rhino...@googlegroups.com
Further to my initial response ....

I think that maybe the dependency graph is your issue. I think what you are trying to do is to test your POCO objects, which you are finding difficult to do because in the current design there are some hidden, hard coded volatile dependencies.

Once you have broken these dependencies your problem will disappear (at least I think that's the case, if I've interpreted the combination of your question and the Telerik link you posted).

jdl

unread,
Sep 14, 2012, 8:37:09 AM9/14/12
to rhino...@googlegroups.com
Bill, 

I am the first to admit that when it comes to mocking it is a fairly grey cloud. I work in a large development group but run my own team and we put out some fantastic software that is used both internally and externally to the company. I am always looking to advanced my knowledge and the art and mocking is always something I wanted to spend the time to know, appreciate and embrace. The "wall" that I am hitting is that most of the times these days I am working deep in WCF web services, yes with POCO's and the first real world example that I want to try this out out is seemingly a complicated one.

To be completely honest, this whole process started because I wanted to break my dependency on a dev sql database where my unit tests were purging the tables before each test run as it constrains me with continuous integration as well as other devs might be looking at something else in the data and it be pulled out from underneath them.

Would it be helpful to provide a sample? I would be happy to do so but do not want to overstep my welcome. I had written a sample for Telerik a few days ago that is a barebones WCF service that simply supports the adding and updating of a user object that  as designed today, using OpenAccess, requires there be a live SQL db on the other day.

An idea I was kicking around with respect to mocking ObjectScope was to also mock the transaction which would allow me to transactionally keep it open over the life of the unit test and leverage FlushChanges() which will move items onto the queue to be committed to SQL (which has the benefit of also supplying the autoinc ID's for the POCO's) but never calling SaveChanges() which would commit the operation. 

I realize this is going the opposite direction of breaking SQL dependency (actually increases it) however for this instance, it would suit my needs. 

At the end of the day I am just trying to add another tool to the toolbox :)

Thanks,

Jim

bill richards

unread,
Sep 16, 2012, 5:48:02 PM9/16/12
to rhino...@googlegroups.com

Before I start ... I know that this is a RhinoMocks thread, but please accept that I've not been using Rhino for the past seven months and am a little rusty on the syntax, so in my tests take them as pseudo code rather than the actual tests, because the syntax is most likely wrong.

.. and oh yeah, it's a long one.

We have a component upon which the application currently has a dependency. The component (OpenAccess) is not under our control, and we have to take it as written that it has been fully tested prior to release, and therefore it does what it needs to do.

public static class DataAccess
{


 public static Guid AddUser(string name, int legacyId = -1)
 {
  try
  {
   using (var model = new VerifyModel())
   {
    User userEntity = GetUserEntity(name);
    if (userEntity != null)
     return userEntity.Guid;
    
    var newUser = new User { Name = name, LegacyId = legacyId };
    model.Add(newUser);
    model.SaveChanges();
    UserContainer.Instance.Refresh();
    return newUser.Guid;
   }
  }
  catch (Exception exception)
  {
   ErrorLogWriter.Write(MethodBase.GetCurrentMethod().Name, exception);
  }
  return Guid.Empty;
 }
}

There are a couple of dependencies in this first method, which need to be made explicit, namely ErrorLogWriter, and UserContainer.

There are three approaches available to us once we have accepted that we need to address the issue by using Dependency Injection (DI): Method Injection; Property Injection; or Constructor Injection.

To use constructor injection would require us to make the class non-static, make the method non-static, create a constructor, and pass both ErrorLogWriter and UserContainer in as parameters.

public class DataAccess
{
 private readonly LogWriter _errorLogWriter;
 private readonly Container _userContainer
 
 public DataAccess(LogWriter errorLogWriter, Container userContainer)
 {
  _errorLogWriter = errorLogWriter;
  _userContainer = userContainer;
 }
 
 public Guid AddUser(string name, int legacyId = -1)


 {
  try
  {
   using (var model = new VerifyModel())
   {
    User userEntity = GetUserEntity(name);
    if (userEntity != null)
     return userEntity.Guid;
    
    var newUser = new User { Name = name, LegacyId = legacyId };
    model.Add(newUser);
    model.SaveChanges();

    _userContainer.Refresh();


    return newUser.Guid;
   }
  }
  catch (Exception exception)
  {

   _errorLogWriter.Write(MethodBase.GetCurrentMethod().Name, exception);
  }
  return Guid.Empty;
 }
}

This involves a considerable amount of change. I won't go in to Property Injection because this is really only achievable when utilising a DI container, which we have not brought in to the solution; but we can look at Method Injection, which would result in the least amount of change for our class and for its callers.

public static class DataAccess
{
 public static Guid AddUser(LogWriter errorLogWriter,
          Container userContainer,
          string name, int legacyId = -1)


 {
  try
  {
   using (var model = new VerifyModel())
   {
    User userEntity = GetUserEntity(name);
    if (userEntity != null)
     return userEntity.Guid;
    
    var newUser = new User { Name = name, LegacyId = legacyId };
    model.Add(newUser);
    model.SaveChanges();

    userContainer.Refresh();


    return newUser.Guid;
   }
  }
  catch (Exception exception)
  {

   errorLogWriter.Write(MethodBase.GetCurrentMethod().Name, exception);
  }
  return Guid.Empty;
 }
}

now our DataAccess class does not know about the type of LogWriter being used, nor does it know about the type of Container being used, so now these things are not dependent upon some static objects, and it is clear to any caller that this member requires a LogWriter and a Container. As far as the DataAccess object is concerned however, so long as they simply ARE instances of LogWriter and Container, then that is all that matters.

We have quite easily broken the dependencies in such a way that we are now able to Mock both logging and Container interaction. For example

public class DataAccessTestFixture
{
 [Test]
 public void WhenNewUserIsSuccessfullyAdded_ThenTheContainer_ShouldBeRefreshed()
 {
  // Arrange
  var mockLogWriter = MockRepository.GenerateMock<LogWriter>();
  var stubContainer = MockRepository.GenerateStub<Container>();
  
  // Act
  DataAccess.AddUser(mockLogWriter, stubContainer, "test user");
  
  // Assert
  stubContainer.AssertWasCalled(c => c.Refresh()).Times(1);
 }
 
 [Test]
 public void WhenAddingANewUserFails_ThenTheLogWriter_ShouldBeInvoked()
 {
  // Arrange
  var exception = new Exception();
  var stubLogWriter = MockRepository.GenerateStub<LogWriter>();
  var stubContainer = MockRepository.GenerateStub<Container>();
   /* enables us to mock a failure */
  stubContainer.Stub(c=> c.Refresh()).Throws(exception);
  
  // Act
  DataAccess.AddUser(mockLogWriter, stubContainer, "test user");
  
  // Assert
  stubLogWriter.AssertWasCalled(w => w.Write("AddUser", exception)).Times(1);
 } 
}

This however will only be possible if LogWriter.Write() and Container.Refresh() are virtual members. If this is not the case then we can introduce our own interfaces for logging and container interaction, we can call them ILogger and IContainer, and we can expose all of the public members of LogWriter and Container respectively in those interfaces. The implementation of those interfaces will simply be invocations of those members on the actual LogWriter and Container instances. This will then allow us to mock logging and container interaction as per the above psuedo code.

This ultimately results in us having a data access layer which is decoupled from the actual implementation of the data storage layer. Now that we are using interfaces and DI, we can quite easily swap out the data storage mechanism, which is effectively what we have done by using a mocking framework.

We have, however, still not decoupled our application from the data access layer. Undoubtably there are numerous references to DataAccess throughout our codebase, it could be that they are all contained within a single class or assembly, but they are definitely there. So we really need to apply the same logic to our DataAccess as we have to the logger and container ineteraction classes; this means that we should really make DataAccess a non-static class, which means that "maybe we should have gone straight for Constructor Injection over Method Injection?". My personal view is yes we should, but it all depends really on how much is going to change in our codebase as a result; remember that refactoring is about making small changes and keeping our tests running green.

When we have finished our refactoring, we will most likely end up with something akin to the following, which looks remarkably similar to our initial discussion of Constructor Injection.

public interface IDataAccess
{
 Guid AddUser(string name, int legacyId = -1);
}

public class DataAccess : IDataAccess
{
 private readonly ILogger _logWriter;
 private readonly IContainer _container
 
 public DataAccess(ILogger errorLogWriter, IContainer userContainer)
 {
  _logWriter = errorLogWriter;
  _container = userContainer;
 }
 
 public Guid AddUser(string name, int legacyId = -1)


 {
  try
  {
   using (var model = new VerifyModel())
   {
    User userEntity = GetUserEntity(name);
    if (userEntity != null)
     return userEntity.Guid;
    
    var newUser = new User { Name = name, LegacyId = legacyId };
    model.Add(newUser);
    model.SaveChanges();

    _container.Refresh();


    return newUser.Guid;
   }
  }
  catch (Exception exception)
  {

   _logWriter.Write(MethodBase.GetCurrentMethod().Name, exception);
  }
  return Guid.Empty;
 }
}

Now, throughout the application, we should only speak in terms of IDataAccess, ILogger, and IContainer, which means that we have completely decoupled the callers from any specific implementations. We can test everything in isolation (erm, I know I didn't test drive this refactoring, but it was omitted for berevity -as if this post is brief!), and we can even change our data access layer and/or our data storage mechanism on a whim (or for genuine reasons) without the need to recompile the whole application.

I know I've rambled, and now that I've reached this point I'm not sure if I'm actually answering any questions! So, the submit button will be pressed and any responses are welcome.

bill richards

unread,
Sep 17, 2012, 4:24:00 AM9/17/12
to rhino...@googlegroups.com
And another note now that I've been thinking about your "issue" ...

You are absolutely right to be breaking the SQL db dependency. Your UNIT TESTS should never go near a database, the database should only really come into the picture at the Integration Test level, I have been using Bob Martin's FitNesse for a while now, and in fact we are rolling it out as the Integration Test Framework across the entire development department here.

I don't particularly like the tool itself, but I really do like what the tool represents and enables and in the absence of anything better, it is fit for purpose (if you'll excuse the pun). It enables us to capture all domain information and our user stories within the Wiki, and then to hook those stories up to acceptance tests by using the FITRunner. This means that the Product Owners can use the same tool as the developers to write out their requirements in plain English, which ultimately results in our domain specific language, and ALL of it is captured within our tests. This of course has the added benefit that any developer can join any project and get up to speed in a matter of hours simply by reading and running the test suite :)
Reply all
Reply to author
Forward
0 new messages