Unit Testing & CSLA

Unit Testing & CSLA

Old forum URL: forums.lhotka.net/forums/t/5373.aspx


Pawz posted on Tuesday, September 09, 2008

Hi all,

I've got a question about setting up unit tests for business objects that depend on certain other objects having done their job.

Basically, I've got a JobSchedules BO that I want to test to make sure it's loading up upcoming jobs that need to be manufactured, but in order for a job to be ready for manufacture, there's about half a dozen steps that need to be performed for each job. What's the best way to do this kind of thing? I'm heading down the route of just calling all the business objects in order to set up the job correctly, but I'm a bit worried that if there's a problem with an unrelated BO, this test will fail (ie, if the Materials BO fails, the job may never get ordered, which means it doesn't show up to be scheduled, which means if I test to make sure it's showing up in the Scheduler BO, that test will fail as well, without any clear indication of why). Worst case would be like a top end BO failing (no Job at all!) and like 100 tests go red.

On the other hand, I wouldn't want to script it out either, because I need to know that all appropriate business logic has been applied at all stages. I'm still new to this Test Driven type stuff, so maybe I'm just missing something simple?



Fintanv replied on Wednesday, September 10, 2008

What you need is a "mocking" framework.  Essentially the mocking framework will intercept certain calls and substitute some other value/object.  In your example you could mock the half dozen steps and then test only the bit of code you actually want to exercise.

Take a look at the following for some further info:

http://www.nermins.net/post/2007/04/TDDUsing-Mock-objects-with-CSLANet.aspx

coding replied on Tuesday, March 10, 2015

Hi 

 

nermins.net url is not working , kindly please share the updated link for TDD with csla

nermin replied on Wednesday, September 10, 2008

An excellent question.  And this has been the only big issue with Csla, or any tightly integrated system.  On one hand you gain so much – if you take a look at the architecture of an Enterprise System built on Csla, and comparably sized one built on another technology, you will see that ones built on Csla are by far simpler.

 

But that tight integration results in complications when it comes to Unit testing.  But before I get to the point of what is the problem in testing scenarios in Csla, let me take a bit longer route explaining how is isolating of objects being Unit tested done.

 

When you unit test your JobSchedules BO, you need to mock calls to some of the objects that it depends on, and just assure that internally JobSchedules is calling the methods with expected parameters.  Those would be your mocks.  In some other dependencies in order to test the functionality inside JobSchedule, dependency object needs to return a pre-packaged set of values in order for your tests on JobSchedule to run.

 

For example each job might have a list of materials, that the job is calculating the total cost for.  Since the iteration, and the calculation is run on the Job object, you need that pre-packaged set from MaterialList BO without running the full MaterialList BO (it executing its own internal methods that like you said can fail for other reasons, then having perhaps other dependencies like database, etc).  So in order to avoid that type of dependency you create what is called a Stub.  Stubbing MaterialList would mean again replacing the actual object with a Stub one that when you call, lets say GetListOfItemsAndPrices() methods on it returns a pre-packaged response that the JobSchedules BO can use in its test.

 

Now since I mentioned two types of Fake objects that helps us isolate our unit of testing (JobSchedules in this case), for different cases, the question becomes how does one create Mocks and Stubs.

 

There are 2 ways:

-          Static Mocks and Stubs

-          Dynamic Mocks and Stubs

 

Static ones are created by subclassing – in order to create a MaterialList Stub, you create an object that inherits from it, then override the GetListOfItemsAndPrices() to return the set of data needed for your test.

For static Mocks, you generally tests situations like if a certain condition is met on JobSchedules then we call method A() on Material BO dependency, or if condition fails, you call method B().  Solution again is subclassing, overriding methods A() and B() to do nothing other than increasing a counter properties like ACalledNTimes, or BCalledNTimes which are also defined on you static mock object that subclasses Material BO for example.

 

The problem with static Mocks and stubs is that they result in a lot of code.  Lets go to MaterialListStub, and GetListOfItemsAndPrices().  What if I want to test how JobSchedules responds to several different scenarios, in other words one scenario where GetListOfItemsAndPrices() returns several valid items and prices, and then second one where prices are missing on some of the elements, or third where the GetListOfItemsAndPrices() perhaps throws some sort of exception, perhaps FormatException (you still want to test that the code inside your Unit being tested handles the expected exceptions from dependencies).

 

For each of those 3 cases you have to create another Subclass, which returns one of the expectations for GetListOfItemsAndPrices().  That is a lot of code.  This is the reason people came up with dynamic Mock and Stub frameworks.  With this you just say:

1)      I want to create a stub of object MaterialList

2)      When called GetListOfItemsAndPrices() replace its return value with “this object”.

3)      Inject the Stub of MaterialList instead of actual object into JobSchedules

4)      Call the JobSchedules method you are testing

5)      Run your assertions

 

Now lets take a look how would that look in a code of our test:

//Arrange

var fakeItemsPrices = new Dictionary<Item,Price>(){ new…, new…, …};

 

var materialList = MockRepository.GenerateStub<MaterialList>();

materialList.Stub(f => f. GetListOfItemsAndPrices ()).Return(fakeItemsPrices);

 

//Action

var jobSchedules = new JobSchedules(MaterialList);

var result = jobSchedules.ActionTested();//this is where the call to GetListOfItemsAndPrices() occurs

//Assert

Assert.AreEqual(Expected_Value, result….)

 

Which finally brings me to a problem in testing scenario in Csla.  HOW DOES ONE INJECT THESE FAKE OBJECTS (STUBS AND MOCKS) during the tests and replaces the actual Csla BO dependencies for JobSchedules?

 

In order for that to happen – in general, outside Csla, people use what is called a Dependency Injection pattern.  They create constructor overloads where they pass as parameters references to all dependencies their object interacts with.  So what that means is that JobSchedule would have a 2 constructors:

private JobSchedule() : this (new MaterialList()){

}

Public JobSchedule(MaterialList materialList){

  this. materialList = materialList;

}

 

As you can see all the first constructor does is – it calls the second one passing it a new instance of the MaterialList.  Second constructor then “injects” that referenc into internal field to be used for later.  But second constructor is also key for our tests, as suring the tests we can pass Static/Dynamic Mock of MaterialList instead of the actual object, as seen in following 2 lines of the example above:

var materialList = MockRepository.GenerateStub<MaterialList>();

var jobSchedules = new JobSchedules(MaterialList);

 

 

BUT THAT EXAMPLE WILL NOT WORK ON CSLA! Why?  CSLA BOs are Mobile Objects, they live in multiple contexts, and are generally created in Server Context, not client context.  That means – we do not call constructors directly (and that is the reason why constructor are generally private).  Object is constructed on the server and then serialized back to the client.  We also generally use Factory Methods to get instances of our Csla BOs.

 

So how does one “INJECT” dependency into Csla BOs during tests.  One solution (which will cost you) is to use TypeMock/Isolator dynamic mocking framework.  There are 3 bing names in Dynamic Mocking frameworks in .Net: Example above was using RhinMocks 3.5 (by far the most popular Mocking framework in .Net).  Then there is a newcomer Moq which works only on .Net 3.5, and already mentioned TypeMock (renamed to Isolator in version 4.2).  RhinoMocks and Moq can only work in scenarios where Dependencies are injected directly into constructor, or perhaps property sets before one calls method being tested.

 

TypeMock/Isolator does not need that. You can state replace this object, and a call on its method with this value (which will happen later in the test) without having an access to the reference that you need to mock.  In other words, MaterialList can be constructed completely internally in JobSchedule object with no outside visibility, and you can still replace the actual MaterialList instance with your Dynamic Mock/Stub.

 

How?  TypeMock, unlike other dynamic mocking frameworks uses Profiler API, allowing it to replace the actual objects/calls during runtime.  You do not need to touch your code in order to make it “testable”.  So the example test from above remains the same except that instead of calling this line to create your jobSchedule:

 

var jobSchedules = new JobSchedules(MaterialList);

 

is replaced with Csla standard Factory Method (constructed the same way as when you use it in code):

 

var jobSchedules = new JobSchedules.CreateNew();

 

The problem with the TypeMock/Isolator is that it will cost you (few hundred per developer).  There was a free community version that is powerful enough for these types of tests (which I used few years back), but they changed it recently so that after 30 days it throws very annoying popups after each test run. 

 

So I gave up on TypeMock/Isolator, for RhinoMocks.  And when I construct my objects, I try to make dependencies “Lazy Loaded”, something like, lets say that the MaterialList is exposed as Property on JobSchedules, like:

public MaterialList Materials{

  get{

    if(_materials==null) _materials = LoadMaterials();

    return _materials;

  }

  set{ _materials = value}

}

 

Then in my test I can set the Materials Property to a value of my Mock MaterialList, prior to running test method.  Sometimes that is impossible (performance might dictate minimizing round-trips to the server, or something of that sort so all dependencies/children are loaded inside root Fetch), and the only solution is to create a public overload of the constructor on the JobSchedule.  Problem with that is that then if your test  constructs the object by calling a constructor overload and the runtime uses FactoryMethods, we might miss some of the initializations performed inside Factory Method, and DataPortal_XYZ.

 

Due to that in this upcoming version of Csla.Net we are coming up with a concept of ObjectFactory, which will allow us to route calls on:

DataPortal.Create<JobSchedule>() to our own Factory that determines what gets called during construction (including DataPortal_XYZ) methods.  With getting that level of control, we actually get the ability to replace the behavior inside the DataPortal_XYZ, and mock dependencies constructed there.

 

We are working on this right now, so please stay tuned and follow both of our blogs for examples of unit tests on that implement ObjectFactory.  My blog is at www.nermins.net, and you will find some of the (older) examples of the dynamic mocking using TypeMock.  Some of the new examples will utilize the ObjectFactory and will be a part of Csla MVC demo (source of which can be already found on my most recent blog post).

 

 

Nermin

 

From: Pawz [mailto:cslanet@lhotka.net]
Sent: Tuesday, September 09, 2008 7:44 PM
To: Nermin Dibek
Subject: [CSLA .NET] Unit Testing & CSLA

 

Hi all,

I've got a question about setting up unit tests for business objects that depend on certain other objects having done their job.

Basically, I've got a JobSchedules BO that I want to test to make sure it's loading up upcoming jobs that need to be manufactured, but in order for a job to be ready for manufacture, there's about half a dozen steps that need to be performed for each job. What's the best way to do this kind of thing? I'm heading down the route of just calling all the business objects in order to set up the job correctly, but I'm a bit worried that if there's a problem with an unrelated BO, this test will fail (ie, if the Materials BO fails, the job may never get ordered, which means it doesn't show up to be scheduled, which means if I test to make sure it's showing up in the Scheduler BO, that test will fail as well, without any clear indication of why). Worst case would be like a top end BO failing (no Job at all!) and like 100 tests go red.

On the other hand, I wouldn't want to script it out either, because I need to know that all appropriate business logic has been applied at all stages. I'm still new to this Test Driven type stuff, so maybe I'm just missing something simple?





SonOfPirate replied on Wednesday, September 10, 2008

Keep in mind that there are two ways to look at your code when developing unit tests - and both are just a valid and I highly recommend implementing both.

The first and simplest are "black box" tests.  When you create a black box test, you are testing the functionality of a piece of code with no regard for how or what it's doing internally to accomplish the task.  An example is calling a service method and evaluating the response.  This can be done at the BO level as well to ensure that things are done correctly.  These tests are great for regression and integration testing later on as well.

However, to be thorough, you need to test how the behavior is implemented. This is typically referred to as "white box" testing (I've heard the term "smoke testing" on occassion, too).  The trick here is to evaluate every possible path through your code, including error conditions, to make sure that the code handles every scenario correctly.  So, if you are examining a method that has limits on values for a specific parameter, your test should call it with a legitimate value AND values that should make the method fail.  If the code behaves one way versus another depending on some object's state, then you need to run the test using every possible state to ensure that the code executes properly.

When using the mock approach described so thoroughly above, keep this in mind and realize that you might have to have multiple mocks in order to fully test your code.  It can get complicated, but the great thing about code-based testing is that it only has to be written once!!!

HTH

 

Copyright (c) Marimer LLC