-
-
Notifications
You must be signed in to change notification settings - Fork 794
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
Add an helper class to simplify parameter capture #251
Conversation
It was not easy to name the class members, for example the I am open to any suggestion or comment. |
Need to think a bit more about this, but it looks interesting... Maybe others can chime in too for feedback? |
This would be really cool, I would like to see matching support with this though, currently it just matches all, while that's the typical use case I've had cases for other captures. You might also want to get the argument for a specific call, so provide index access to the underlying list. |
@hahn-kev I updated the PR to include match support. The new syntax is
|
/// <summary> | ||
/// Gets all the captured parameter values. | ||
/// </summary> | ||
public IEnumerable<T> All { get { return _capturedValues; } } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd expose IList to make this more flexible, maybe wrapping a ReadOnlyList?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
a00ddf9
to
d96da91
Compare
I removed the underscores on the private field names to follow the naming rules of the project, sorry about that. |
/// Gets the parameter to use in the setup expression. | ||
/// </summary> | ||
/// <returns>The setup expression parameter</returns> | ||
public T CaptureAny() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think capture.Any()
reads better, and since there is already a Linq Enumerable.Any()
and an overload Enumerable.Any(func predicate)
, I'd propose to make this method and Capture
both named Any
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I choosed the names CaptureAny
and Capture
to match IsAny
and Is
methods but I also like your idea to have only one method name with overloads. However, I think Any
is confusing because the class exposes captured values through methods like All
or Last
. Those methods could be renamed but it seems to me that naming the capture method Capture
is more straightforward. What do you think ?
Ok, I decided to refactor everything to take your remarks into account. I removed
The main use case is now straightforward: // Arrange
var mock = new Mock<IFoo>();
var items = new List<string>();
mock.Setup(x => x.DoSomething(Capture.In(items)));
// Act
// ...
// Assert
var expectedValues = new List<string> { "Hello!" };
Assert.Equal(expectedValues, items); Advanced use cases are still supported using var mock = new Mock<IFoo>();
var captureMatch = new CaptureMatch<string>(s => CustomCode(s));
mock.Setup(x => x.DoSomething(Capture.With(captureMatch))); |
Beautiful! Thanks a lot! |
btw, are you https://twitter.com/ocoanet? |
It is frequently required to capture a mock parameter to perform complex assertions. Parameter capture is a regular request from new Moq users.
It can be done with setups and callbacks, but the syntax can be tricky, especially for methods with many parameters.
This helper class simplifies parameter capture: