1. Public not enough for mocking a class, needs to be virtual. Mocking
interfaces is sooooo much more easier than mocking classes; I never
mock classes, not worth the headache.
2. I'm still not sure you want to mock that, as it's part of the class
you're trying to test, usually it's best to leave private methods
below because it's an implementation detail private to the class. If
your test digs into the private parts of a class the test/class will
be very brittle... better to try and see your class as a complete
object and only mock the dependencies of the class, not its private
methods.
3.Too optimistic, just creating a mock doesn't mean it get used, you
need to pass it to something, whether that's the class itself (usual
way) or to some sort of Service Locator or IoC container.
4. Note in my test below I don't mock WorkProcess at all... that's
kind of what I was getting at
5. I've removed the dependency on DAL by passing in an IDataProvider
explicitly, your next question might be that in production you want it
to access the DAL, in which case there are several possibilities
including "poor man's dependency injection" where you have another
constructor used only in production which uses DAL to populate the
dependency. Or you could use an IoC container...
This is roughly what I'd do (complete example, note no private accessor needed):
public interface IDataProvider
{
Guid ReturnGUIDFromIntegerMapping(int id);
string ReturnConnectionStringFromIntegerMapping(int id);
}
public class WorkProcess
{
public struct TargetDataSetStruct
{
public Guid DataSet_GUID;
public string ConnectionString;
}
public TargetDataSetStruct TargetDataSet
{
get;
private set;
}
public int DataSet_ID
{
get;
set;
}
private IDataProvider dp;
public WorkProcess(IDataProvider dp)
{
this.dp = dp;
}
internal void RunChecks()
{
TargetDataSet = FindDataSetInDatabaseRegister(DataSet_ID, dp);
}
internal TargetDataSetStruct FindDataSetInDatabaseRegister(int
DataSet_ID, IDataProvider dp)
{
TargetDataSetStruct tds = new TargetDataSetStruct();
tds.DataSet_GUID = dp.ReturnGUIDFromIntegerMapping(DataSet_ID);
tds.ConnectionString =
dp.ReturnConnectionStringFromIntegerMapping(DataSet_ID);
return tds;
}
public void ProcessFile()
{
RunChecks();
}
}
[TestClass()]
public class WorkProcessTest
{
[TestMethod()]
public void ProcessFileShouldPopulateDataSetGuid()
{
//Arrange
IDataProvider mockDP = MockRepository.GenerateMock<IDataProvider>();
WorkProcess target = new WorkProcess(mockDP);
int id = 5;
target.DataSet_ID = id;
Guid expected = Guid.NewGuid();
mockDP.Stub(x => x.ReturnGUIDFromIntegerMapping(id)).Return(expected);
//Act
target.ProcessFile();
//Assert
Assert.AreEqual(expected, target.TargetDataSet.DataSet_GUID);
}
}
2009/10/20 Chris <[email protected]>
>
> Hi, Alex.
> Thanks for the reply.
>
> 1. I agree with you on this point, however, since the private accessor
> exposes the given methods as "public" I thought it unnecessary to add
> the "virtual".
> I added the "virtual", still the same exception; failure on the same
> Expect.Call().
>
> 2. Yes. My target is the "ProcessFile"-method. ProcessFile calls
> RunChecks which calls FindDataSetInDatabaseRegister.
> I'm trying to mock away the dependency that ProcessFile has on
> FindDataSetInDatabaseRegister and FindDataSetInDatabaseRegister on the
> IDataProvider.
>
> 3. In another test, not shown here, I do use the DI pattern with the
> IDataProvider correctly. I was hoping that by mocking the
> IDataProvider again in this test, that the mocking framework will
> automatically substitute the IDataProvider when those calls are hit.
> Am I too optimistic in this expectation?
>
> 4. Agreed. That's what I'm trying to do - mock away ProcessFile's
> dependency on FindDatasetInDatabaseRegistry.
>
> 5. The FindDatasetInDatabaseRegistry-method is marked internal and
> calls the DAL which throws a System.NotImplementedException. This is
> a business unit test, not DAL test, so I want to mock away that
> dependency. Just calling ProcessFile (without mocking certain
> methods) in the test will just throw the DAL exception.
>
> 6. Will do. Unfortunately my googling hasn't scared up a similar
> case.
>
> Given my code posted in the thread, could you perhaps knock something
> together to show how you might approach it? The IDataProvider
> interface is just the two methods that FindDatasetInDatabaseRegistry
> call.
>
> On Oct 20, 11:53 am, Alex McMahon <[email protected]> wrote:
> > A few points:
> >
> > 1. To mock a method on a class it must be marked as virtual
> > (FindDataSetInDatabaseRegister is not virtual therefore you can't mock
> > it).
> > 2. Are you sure that's the method you want to mock? it sort of looks like
> > you want to mock the calls to dp.xxxx within that message... if so then
> > you
> > need a way to replace the IDataProvider that is passed into the method.
> > This
> > is currently retrieved from DAL, which I guess is some sort of static?
> > 3. All your test methods create a mock IDataProvider (db) but then never
> > pass this mock into the target. Therefore the mock is never hit. You
> > might
> > want to use Dependency Injection to inject your mock (or real
> > IDataProvider)
> > into the target. Alternatively you could change your DAL class to allow
> > your
> > mock to be returned (I personally wouldn't do this)
> > 4. Usually you wouldn't mock your target, you mock the dependencies of
> > your target instead.
> > 5. Why do you need a private accessor? can't you just create an instance
> > of your target, then call ProcessFile on it (seeing as it's public)
> > 6. A lot of what you've got there doesn't exactly look normal, try
> > looking at Rhino Mocks documentation or some open source projects that
> > use
> > Rhino Mocks to see some examples of how to use it
> >
> > Hope some of that helps.
> >
> > 2009/10/20 Chris <[email protected]>
> >
>
> >
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Rhino.Mocks" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/rhinomocks?hl=en
-~----------~----~----~----~------~----~------~--~---