New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optionally disable caching for AutoMoq? #625
Comments
The idea behind caching the result value was to make all methods pure by default, which is considered a good practice. If the system under test expects a pure function, but is given an impure function, the test is likely to result in a false positive. E.g. // This method will return the expected result *if* `GetInt` is pure.
int Double(IDependency dep) {
return dep.GetInt() + dep.GetInt();
}
Assert.Equal(dep.GetInt * 2, Double(dep)); On the other hand, if the system under test does not assume purity, giving it a pure or impure function should make no difference. Hence, defaulting to pure functions made sense to me when I implemented this feature.
If you need to do this for one method, but across multiple test, I'd put it in a reusable If you want to do this for all methods, across multiple tests, then you'll need a bit more work:
We could also think of a way to make this behaviour configurable, but I'm not sure if the demand is high enough to justify this. Such a change should not be taken lightly, in my opinion - fine-grained customization can lead to accidental complexity. @ploeh, what are your thoughts on this? |
I admit that I thought the test doubles were configured to call back into AutoFixture in order to get a return value. AutoFixture does already have a lifetime management mechanism (via it's Freeze features), so I find it a bit surprising that |
That's a very good point, I never thought about |
Is it behaviour we've documented or somehow 'promised' in tests? |
Surprisingly, no. I was pretty sure I had covered this, but it appears I didn't. At least I couldn't find any test that covers this, and removing that line did not cause any test to fail. However, IMO, it still is observable behavior, and there's likely to be code that relies on this... |
Fair point. Could it be a configuration value that we set to one value now, and then switch it when we transition to AutoFixture 4? |
Agreed. In this context, what exactly do you mean by "configuration value"? Would lifting it to a const inside the |
It was a bit of a throwaway comment, I admit, so I don't know if it'd be practically possible without too many changes. What I meant, though, was this: @andreasnilsen would like to change the behaviour now, but we're concerned that it'd be a breaking change. If we make the behaviour configurable, then we'd give @andreasnilsen a way to change the behaviour now, while we don't break any other clients. When we introduce AutoFixture 4, we change the default configuration, so that the default behaviour then is that return values aren't cached. Or perhaps we simply remove that option... Something like a boolean (Also, unless we're absolutely certain that there's only going to be exactly two values, we should consider an |
Ah, I first thought you meant some internal flag that was easy to spot and change in v4. The first two approaches that come to mind are:
I'm wary of making design decisions that we might regret and be stuck with later, so your expertise/experience maintaining this project would be highly appreciated. |
I was thinking something like a Strategy... |
Ah yes, of course! I guess I was fixated on a "configuration value" and forgot to take a step back. I'm sorry for the late reply, I've been swamped - I'll take a look at this soon and come back with a design proposal. |
Recently we have performed the customization refactoring to use properties for the customization tweaking. Potentially, this feature could be controlled like following (find the better setting name): new AutoMoqCustomization { CacheCallResults = false } Under the hood we could implement that via different strategy like that has been advised above. Marking with a jump in tag, as it should be relatively simple to implement this. |
@zvirja could you help me out a bit and I can work on this one. I just don’t know where to start :) |
@micheleissa Thanks for your interest! I would suggest just reading the If you have more specific question, please ask 😉 |
When using an AutoConfiguredMoqCustomization, the value returned by the used fixture is cached, and the same value will be returned on each invocation (I'm not sure if this is done in MockType.ReturnsUsingContext or somewhere else, but I see a comment about it on line 104 there).
The only way I've found to override it is to pass a Frozen instance of the mock in question into the test method, and override the setup with a func invoking the fixture:
someMock.Setup(it => it.SomeMethodReturningAString()).Returns(() => fixture.Create<string>())
Is there any more generic/smarter way to configure the auto generated mocks to invoke the fixture each time a value is needed from AutoFixture, other than to manually setup each invocation?
The text was updated successfully, but these errors were encountered: