I agree that using Constructor or Property Injection would make my
life easier. Unfortunatley our production app has already had it's IoC
architecture decided -- I'm happy enough to hopefully bring BDD to the
party.

So I was thinking after reading more about AMC implementation and I
found that the concept of providing/injecting an object of your choice
in addition to just providing a type to my service locator would allow
me to create a mock or a stub depending on what I need for the test
and the locator would use that when the SUT asked for it. I also made
the AMC use constructor injection for the mock repository -- the
previous implementation ended up having two, which sounds like a
recipe for disaster.

So I added that feature to our AMC and it solved the two specific
issues I presented! I provided a stub for the IEnterNumber
implementation of the first test, and I provided a mock for the
IEnterDigit in the second. Of course I ran into a third issue though:
I had some code that needed two instances of the same interface, but
since I had provided a stub for the first need the code only had 1
reference and it didn't work. Luckily all I had to do was provide a
second stub instance AFTER the first one was referenced by the code.
It worked perfectly after that.

All in all, I think this AMC is cleaner than it was and I have more
control over what I want to do. I think I might run into trouble later
if I have some code that needs two instances of the same interface but
I don't have the opportunity to step in and provide a second instance
through the locator -- but I'll cross that bridge when I get there.


Thanks Robin,

Dan Lash


On Nov 25, 4:24 pm, Robin Clowers <[EMAIL PROTECTED]> wrote:
> The easier way I think would be to use dependency injection.  If your
> classes take all their dependencies in their constructors, you can
> easily pass real implementations, mocks, or stubs at test time.  You
> could use an IoC container to facilitate the runtime construction of
> objects, and likewise you could use an automocking container at test
> time, but you don't need to.  I am a big fan of StructureMap and it's
> AMC, you can see the usage 
> here:http://codebetter.com/blogs/jeremy.miller/archive/2008/02/09/automock...
>
> On Nov 25, 6:31 am, Dan Lash <[EMAIL PROTECTED]> wrote:
>
>
>
> > I think the root of my problem is using a Service Locator pattern. I
> > want my AMC to use stubs or mocks in different situations, but both
> > tests are 'broken' because I'm using that particular IoC pattern. My
> > code is asking the locator to give it an object that fulfills some
> > interface -- and my test code is either going to want to put
> > expectations on it OR not care about expectations but the object needs
> > to work.
>
> > So I guess an easier way to ask the question is: what is a good way to
> > test interaction when using a service locator pattern?
>
> > If the answer is AMC, how then can you control whether it's dolling
> > out mocks or stubs? And if you can't how can you extract the mocks
> > from your code to use in your test?
>
> > Thanks alot,
>
> > Dan Lash
>
> > On Nov 24, 3:45 pm, Dan Lash <[EMAIL PROTECTED]> wrote:
>
> > > I am working on a test project to prove out TDD/BDD before bringing it
> > > to our next project. The test project is a simple 4-function
> > > calculator and I've been able to get pretty far with state based
> > > testing. Now I'm trying to do some interaction based testing and
> > > running into some challenges.
>
> > > The calculator is using a Service Locator pattern to get the
> > > implementations of the interfaces. Because of this, I thought that the
> > > Auto Mocking Container (or the idea of it) would fit perfectly. But I
> > > have two different situations where I need the AMC to work
> > > differently.
>
> > > First, I am testing that when the Calculator is going to evaluate that
> > > it interacts with the Math Engine properly. I have a test like this:
>
> > > [Test]
> > > public void should_use_math_engine_to_add()
> > > {
> > >     Expect.Call(_firstDigit.Digit).Return(4);
> > >     Expect.Call(_addOperation.Operation).Return
> > > (Calculator.Core.Operations.Add);
> > >     Expect.Call(_secondDigit.Digit).Return(3);
> > >     Expect.Call(_math.Add(4, 3)).Return(7);
> > >     SetupResult.For(_addOperation2.Operation).Return
> > > (Calculator.Core.Operations.Add);
>
> > >     Mocks.ReplayAll();
>
> > >     _calculator.PerformAction(_firstDigit);
> > >     _calculator.PerformAction(_addOperation);
> > >     _calculator.PerformAction(_secondDigit);
> > >     _calculator.PerformAction(_addOperation2);
>
> > >     Mocks.VerifyAll();
>
> > > }
>
> > > The problem I have is that the Calculator implementation uses the
> > > Locator to get an IEnterNumber to append the IEnterDigits before
> > > working with the Math Engine, and since I'm using an AMC it get's a
> > > mock. Since a mock doesn't store properties like stubs do I'm getting
> > > exceptions the mock can't return a value unless you specify it.
>
> > > So one way I could fix that is by making my AMC return stubs instead.
> > > That would allow the calculator to perform it's interaction with the
> > > Math Engine and everything is good. I don't care how it uses
> > > IEnterNumber internally, just that it interacts correctly with the
> > > engine.
>
> > > BUT I have a different test that would have the opposite problem if I
> > > changed it. That test verifys the interaction between my Presentation
> > > Model and my Core. This is how it's set up:
>
> > > [Test]
> > > public void should_perform_enter_digit_action_on_calculator()
> > > {
> > >     _digitAction.Digit = 2;
> > >     _calculator.PerformAction(_digitAction);
>
> > >     _digitAction.GetMockRepository().ReplayAll();
>
> > >     _model.AddDigit("2");
>
> > >     _digitAction.GetMockRepository().VerifyAll();
>
> > > }
>
> > > The way that this test works is it gets the IEnterDigit from the AMC
> > > so it can set up the expectations on the same object that the Model
> > > will use. This test relys on the AMC to give a mock to the Model so it
> > > can have proper expectations set on it.
>
> > > The main difference between the two is that in the first test I don't
> > > care about the use of IEnterNumber because it's all internal -- but I
> > > need it to work close to normal. The second test I care about
> > > IEnterDigit because it's the method of communication between the Model
> > > and the Core -- and I need to set expectations on it.
>
> > > So after all that explanation my question is: am I doing this right?
> > > If both of the tests and my testing strategy seem right, how can I
> > > mock and/or stub properly in both of them when they are using a
> > > Service Locator pattern?
>
> > > I appreciate any advice on this.
>
> > > Dan Lash- Hide quoted text -
>
> - Show quoted text -
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to