0

I have a method that takes multiple implementations of a single-method interface and executes them in turn. Each of these mutates ValueType in some way.

public interface IValueTypeMutator
{
    ValueType ModifyValueType(ValueType valueType);
}

public class ValueTypeBuilder
{
    public ValueType Create(params IValueTypeMutator[] mutators)
    {
        var valueType = new ValueType { X = "SomeConstant" };

        return mutators.Aggregate(
            (valueType, mutator) => mutator.ModifyValueType(valueType));
    }
}

When I'm testing a class that uses a ValueTypeBuilder, each IValueTypeMutator will be a stub. To maintain the state of my ValueType after initialisation, for some tests, I want the stub to simply echo the value of the ValueType input as the return value.

This is necessary because without an explicit Stub() implementation, the default behaviour of the stub is to return null, which will overwrite the initialisation of ValueType earlier in the Create() method. Defining the actual values used in ValueType's initialisation would, however, cause the tests to become unnecessarily brittle: the precise initialisation of ValueType is not relevant to these particular tests, just that its state is maintained.

Richard Walton
  • 4,789
  • 3
  • 38
  • 49
jcorcoran
  • 253
  • 1
  • 9

2 Answers2

2

RhinoMocks Do() Handler fits the bill here.

    _stubMutator = MockRepository<IValueTypeMutator>();
    _stubMutator
        .Stub(x => x.ModifyValueType(Arg<ValueType>.Is.Anything))
        .Do((Func<ValueType, ValueType>) (v => v));

In this case, the precise initialisation of ValueType isn't the subject of the test so I've used Arg<ValueType>.Is.Anything to ensure the identity function is called regardless of the value of ValueType.

jcorcoran
  • 253
  • 1
  • 9
  • I can't help but think that this is no longer a `Stub` but a `Fake`. http://stackoverflow.com/a/6808251/1808494 – Aron Apr 07 '14 at 17:49
  • I'm not sure it's entirely clear exactly when a `Stub` becomes a `Fake`; let's instead assume we're talking about a Rhino Mock `Stub`. My Rhino Mock `Stub` (which isn't actually prefixed with `_stub` in the real code) is used in some tests as a mock as well for `AssertWasCalled` because in Rhino Mocks you can do ["pretty much anything with a `Stub`"](https://raw.githubusercontent.com/JonKruger/RhinoMocksExamples/master/src/RhinoMocksExamples/RhinoMocksTests.cs). It seems like most mocking frameworks don't make the stub/mock distinction these days either. – jcorcoran Apr 09 '14 at 13:32
  • The difference in my mind between a Fake and a Stub is that a Fake is a working implementation of an interface or class, whilst a Stub is used much like a MacGuffin is in literature. In this case, the Fake would have to return something resembling a ValueType. Whilst a Stub could and should return null. The behavior of the Stub should not affect the test, but obviously if it you chained the Stub with other Mutators, then we would have a NullException. – Aron Apr 10 '14 at 06:45
  • Why _should_ a stub return null? Also, like I said, my use of the word stub is here purely in the Rhino Mock sense of the word. In other tests my stub behaves like a mock where I use `AssertWasCalled`. Just because my stub is behaving in some sense like a fake, if indeed it is, why should I avoid using the Rhino Mock stub functionality? This is one of the simplest uses of Do() I can think of: an identity function. – jcorcoran Apr 11 '14 at 10:09
  • Okay...perhaps I wasn't clear. I am not using what you call "Rhino Mock sense of the word", because as you noted, its not what you use, but how you use it. Rhino Mock's Mocks by default are good for Mock testing, which includes such `ExpectWasCalled`. Whilst Stub is a dynamic object that only just satisfies what the test requires of it. However a Fake can be used for ALL tests related to it, because it is a working class. A Stub does not satisfy the "code contract" of the interface, whilst a Fake does. This means you should be able to run your Unit Tests against the Fake as well. – Aron Apr 11 '14 at 10:22
  • I am using Martin Fowler's definitions by the way http://stackoverflow.com/a/346440/1808494 I highly recommend reading Martin Fowler's essay. As it concretes my reasons for preferring a Fake to a Stub/Mock in this case. – Aron Apr 11 '14 at 10:23
  • There are quite a lot of points to discuss here, but I'll select one: how would you assert that a `FakeValueTypeMutator` has been called given that it does not change any testable behaviour? – jcorcoran Apr 11 '14 at 11:53
  • Then your test is as much about your `Mutator` as your `ValueTypeBuilder`. In that case you need `Mock Testing`. You are actually wanting to Assert your call invoked. Although you could put a counter into your Fake. – Aron Apr 11 '14 at 16:30
0

I can't help but think that shirley you could actually use either Fake or the Real IValueTypeMutator. There is nothing wrong with using concrete classes for Unit Testing. In this case I would slip private class FakeValueTypeMutator into the test class. Its much clearer what is going on.

[TestFixture]
public ValueTypeBuilderTest
{
    private class FakeValueTypeMutator : IValueTypeMutator
    {
        public ValueType ModifyValueType(ValueType valueType)
        {
            return valueType;
        }
    }

    //Test code here!
}
Aron
  • 15,464
  • 3
  • 31
  • 64