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

WherePasses and WhereThrows to Linq to Mocks #613

Closed
Arithmomaniac opened this issue Apr 9, 2018 · 3 comments
Closed

WherePasses and WhereThrows to Linq to Mocks #613

Arithmomaniac opened this issue Apr 9, 2018 · 3 comments

Comments

@Arithmomaniac
Copy link

It would be nice to use Linq to Mocks in the following two scenarios:

WherePasses

Instead of having to always instantiate a strict mock with a void method like so:

var objectMock = mockRepository.Create<IFoo>();
objectMock.Setup(x => x.VoidMethod());
var obj = objectMock.Object;

It would be nice to have

var obj = mockRepository.Of<IFoo>()
    .WherePasses(x => x.VoidMethod())
    .First();

This could be implemented by creating an internal method ExpressionPasses<T>(T obj, Expression<Action<T>> expression), which can be detected during expression parsing, and then interpreting the above line as

var obj = mockRepository.Of<IFoo>()
    .Where(x => ExpressionPasses(x, y => y.VoidMethod()))
    .First();

Instead of adding WherePasses as an extension on IQueryable, I would expose an inheriting interface specifically for Linq to Mocks (IMockQueryable?) and add the method to that.

WhereThrows

Similarly, for methods that throw simple exceptions,

var obj = mockRepository.Of<IFoo>()
    .WhereThrows<InvalidOperationException>(x => x.AnyMethod())
    .First();
@stakx
Copy link
Contributor

stakx commented Apr 11, 2018

@Arithmomaniac:

WherePasses:

Having a .WherePasses operator seems rather pointless to me: Since mocks that are set up with Mock.Of are not strict mocks, mock methods won't throw by default. Telling the Moq they shouldn't throw is a waste of time. (I am following the argument that xUnit made against Assert.DoesNotThrow.)

WhereThrows:

There is perhaps a case to be made for WhereThrows, but I see a couple of problems:

  • .Of<T>() returns a T, not an IQueryable<T>, so everything that comes after it (such as WhereThrows, First) is a little late to the party.

  • Mock.Of<T>() is currently geared towards setting up object data, not behavior. As such it is a very simple API that, for this reason, is often more convenient than the full, traditional Setup-based API. It doesn't have to stay that way forever of course, but I do wonder what's the point in inflating the former to be as feature complete as the latter. Does Moq really need two parallel APIs? That would incur quite a large (and avoidable) maintenance cost. Would you really be saving much time by using Mock.Of<T>().WhereX(...).First() instead of new Mock<T>().Setup(...)? (That's just my personal opinion.)

From this point onwards, new features should probably be discussed over at the Moq 5 repo.

Finally, we've put a freeze on Moq 4's API at this time so that Moq 5 can be made ready for release. After that, I expect that Moq 5 will become the leading project with respect to Moq's API, so if you'd like to implement and merge this new functionality into Moq, perhaps it would be best to deal with this over at https://github/moq/moq (the repo for Moq 5).

@Arithmomaniac
Copy link
Author

mocks that are set up with Mock.Of are not strict mocks

.Of() returns a T, not an IQueryable

Are you confusing Mock.Of<T>() (which cannot be a strict mock, and returns T) with new MockRepository(MockBehavior.Strict).Of<T>() (which returns IQueryable<T>)?

Would you really be saving much time by using Mock.Of().WhereX(...).First() instead of new Mock().Setup(...)?

Potentially a lot of time, if you need to set up a ton of things, but have a void or error-throwing method. (#293 would fix this.)

From this point onwards, new features should probably be discussed over at the Moq 5 repo.

I don't mind reposting there.

@stakx
Copy link
Contributor

stakx commented Jul 13, 2018

I am closing this issue, as per the above; we definitely shouldn't put an issue with much potential for follow-up API changes in "mostly-maintenance" Moq 4.

@stakx stakx closed this as completed Jul 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants