An occasional question that comes up on the
jMock users' mailing list is how to mock casts? This is, I guess, mostly needed when interfaces are used to define capabilities of an object that are dynamically discovered by some other object in the system, somewhat like this:
public class Juicer {
public void juice(Juiceable fruit) {
if (fruit instanceof Peelable) ((Peelable)fruit).peel();
fruit.juice();
}
}
If you create a mock Juiceable object when testing the Juicer, how can you create an expectation for the cast to Peelable and make it return a mock Peelable?
Casts and the
instanceof
operator are implemented at the language/VM level and cannot be mocked out. However, you don't need to mock them at all . You can instead define an interface in your test that can be cast to the required interface and mock that.
public class JuicerTest extends MockObjectTestCase {
interface PeelableAndJuiceable implements Peelable, Juiceable {}
public void testPeelsPeelableFruitBeforeJuicing() {
PeelableAndJuiceable fruit = mock(PeelableAndJuiceable.class, "fruit");
Juicer juicer = new Juicer();
expects(new InThisOrder() {{
exactly(1).of (fruit).peel();
exactly(1).of (fruit).juice();
}});
juicer.juice(fruit);
}
}
David Saff makes a good point: "[You might] find that the new interface captures a new abstraction in your code that is useful in other places. In my experience, if it's worth testing, it's often worth naming."
2 comments:
i'd like a sample in C# for NMock2 please.
Thanks.
AC.
public interface IPeelableAndJuiceable : IPeelable, IJuiceable { }
private IPeelableAndJuiceable m_produce;
.
.
.
Expect.Once.On(Pantry).Method("GetProduce").
With(Is.EqualTo("Fruit")).
Will(Return.Value(m_produce));
Post a Comment