When you have inter-related calls like that it gets a bit trickier. Mandatory disclaimer: if we need to have a more realistic implementation like this, it might be worth implementing a test variant of the class/interface instead of configuring it with a mocking library. We can then also test this test code to make sure it is adhering to the correct contract. I normally find mocking works best when we really don't care about a specific implementation of a dependency, we just want to make sure our code under test calls a dependency when expected and uses returned values correctly, independent of any particular implementation or call ordering.
With that out of the way, here's one way of doing something like this... :)
DbData data = null;
sub.GetData().Returns(x => data);
sub.CreateData().Returns(x => {
data = new DbData("my sample data");
return true;
});
This will make `GetData()` return whatever is in the `data` variable. Initially it is `null`, but after a call to `CreateData()`, it will be populated with sample data.
It might be worth seeing if you can instead split up the design of the tests (or the production code if necessary) a bit to reduce this coupling. For example, we could test:
[Test] public void CreatesDataIfNoDataPresent() {
sub.GetData().Returns(null);
classUnderTest.DoStuff();
sub.Received().CreateData();
}
[Test] public void DoesNotCreateDataIfAlreadyHasData() {
sub.GetData().Returns(data);
classUnderTest.DoStuff();
sub.DidNotReceive().CreateData();
}
[Test] public void UsesDataCorrectly() {
// for this case it shouldn't matter if data was already there, or was added via CreateData()
sub.GetData().Returns(data);
classUnderTest.DoStuff();
Assert(stuffHappenedWithData);
}
[Test] public void IfCreateDataFails() {
sub.GetData().Returns(null);
sub.CreateData().Returns(false);
classUnderTest.DoStuff();
Assert(theRightThingHappened);
}
I think this side-steps the coupling issue between calls to this dependency, and will hopefully provide us with a very specifically-failing test if something is not working (rather than having one larger test breaking for a number of potential reasons).
YMMV of course, and I understand the actual case you're looking at may be much more complicated etc., but thought it was worth mentioning in case it gave you some ideas for alternate approaches that may work more nicely here.
Regards,
David