Skip to content
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

Enable multi-method setups #1203

Merged
merged 4 commits into from
Aug 24, 2021

Conversation

stakx
Copy link
Contributor

@stakx stakx commented Aug 24, 2021

This refactoring of Moq internals enables setups that handle more than just a single method.

I have two use cases in mind:

  1. StubbedPropertyGetterSetup and StubbedPropertySetterSetup could be merged into a single setup type. This would be more efficient than what we have now, and also better capture the semantics of a call to mock.SetupProperty().

  2. It would allow creation of a new setup type StubbedPropertiesSetup backing mock.SetupAllProperties(). This could keep track of any number of properties' values in a dictionary. Again, this would be more efficient than the current solution, allow us to get rid of some convoluted internal bits (such as SetupCollection.RemoveAllPropertyAccessorSetups), and it may help solve Property setups are ignored on mocks instantiated using Mock.Of #1066.

The difference between those two classes being that `Expectation` isn't
necessarily bound to a single, specific method.

Then make `Setup` use `Expectation` instead so that the types correspond
as follows:

          `Setup`  <->        `Expectation`
    `MethodSetup`  <->  `MethodExpectation`
But don't expose that fact via `ISetup.InnerMock[s]` just yet; see the
code comment in `ISetup` for an explanation.
Comment on lines +19 to +23
public virtual bool HasResultExpression(out IAwaitableFactory awaitableFactory)
{
awaitableFactory = null;
return false;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method doesn't really fit in very well here, as it doesn't have much to do with the core purpose of Expectation.

A possibly better design might be to create a custom LINQ expression tree node type ResultExpression (which would carry the IAwaitableFactory as data), then add such a node directly to Expression.

That can be done as a separate refactoring another time.

Comment on lines +36 to +38
public virtual void SetupEvaluatedSuccessfully(Invocation invocation)
{
}
Copy link
Contributor Author

@stakx stakx Aug 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also doesn't fit in very well here.

I'm not yet sure how to get rid of it. A few possible options off the top off my head:

  • Let Expectation expose its argument matchers through a property. When a setup is successfully matched, Setup could then skip over Expectation.SetupEvaluatedSuccessfully and call the matchers' SetupEvaluatedSuccessfully methods directly.

  • Add an event Setup.Matched, to which argument matchers may optionally subscribe their SetupEvaluatedSuccessfully methods.

The first option seems like the more plausible in the short term. It doesn't make much sense to add a Matched event just to get rid of this method here, however that solution may start to look more plausible if the event is going to get added to also support other features (such as better support for sequences).

this.setups.RemoveAll(x => x.Method.IsPropertyAccessor());
this.setups.RemoveAll(s => s is MethodSetup ms && ms.Method.IsPropertyAccessor());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bad change, but acceptable if it means we'll soon be able to remove this whole method.

@stakx stakx merged commit d107842 into devlooped:main Aug 24, 2021
@stakx stakx deleted the refactor/enable-multi-method-setups branch August 24, 2021 14:14
@aysan0
Copy link

aysan0 commented Sep 27, 2021

@stakx, thanks for completing this. What version of MoQ will this change be in?

@stakx
Copy link
Contributor Author

stakx commented Sep 27, 2021

@aysan0, this change was made mainly to pave the way for fixing #1066. For now, it remains strictly an implementation detail, and this will probably not be exposed in any public API anytime soon. (The likely moment for making this public would be when we allow user code to add fully custom Behavior setups... I had a WIP pull request about that a while ago but it wasn't ready yet.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants