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

Function match should catch exception? #1010

Closed
dawncold opened this issue Apr 27, 2020 · 5 comments
Closed

Function match should catch exception? #1010

dawncold opened this issue Apr 27, 2020 · 5 comments

Comments

@dawncold
Copy link

dawncold commented Apr 27, 2020

Moq version: 4.14.0

When I run test like this, I got an exception, it looks like Single method raise exception when a list with two or more elements passed to it.

Workaround code:
change m.Actions.Single() == Action.View to m.Actions.Count == 1 && m.Actions[0] == Action.View

I'm not sure whether it is possible when match function throws an exception, as a mismatch?

This is my test codes

public class Test
{
    [Fact]
    public void test()
    {
        var mockedPermissionService = new Mock<IPermissionService>();
        mockedPermissionService.Setup(lib =>
            lib.Permission(It.Is<PermissionRequest>(m =>
                m.SubjectId == 1 && m.Actions.Single() == Action.View)))
            .Returns(1);
        mockedPermissionService.Setup(lib => 
                lib.Permission(It.Is<PermissionRequest>(m =>
                    m.SubjectId == 1 && m.Actions.Count == 2)))
            .Returns(2);
        mockedPermissionService.Setup(lib => 
                lib.Permission(It.Is<PermissionRequest>(m =>
                    m.SubjectId == 1 && m.Actions.Single() == Action.Delete)))
            .Returns(3);

        var permissionService = mockedPermissionService.Object;
        var result1 = permissionService.Permission(new PermissionRequest
        {
            Actions = new List<Action>{ Action.View },
            SubjectId = 1,
            ObjectId = 1
        });
        var result2 = permissionService.Permission(new PermissionRequest
        {
            Actions = new List<Action> { Action.View, Action.Delete },
            SubjectId = 1,
            ObjectId = 2
        });
        Assert.Equal(1, result1);
        Assert.Equal(2, result2);
    }
}

Exception:

TestMoq.Test.test

System.InvalidOperationException: Sequence contains more than one element

System.InvalidOperationException
Sequence contains more than one element
   at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
   at lambda_method(Closure , PermissionRequest )
   at Moq.InvocationShape.IsMatch(Invocation invocation)
   at Moq.SetupCollection.FindMatchFor(Invocation invocation)
   at Moq.FindAndExecuteMatchingSetup.Handle(Invocation invocation, Mock mock)
   at Moq.Mock.Moq.IInterceptor.Intercept(Invocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.IPermissionServiceProxy.Permission(PermissionRequest request)
   at TestMoq.Test.test() in C:\Users\Administrator\RiderProjects\TestMoq\TestMoq\Program.cs:line 34
@dawncold dawncold changed the title MethodCall Matches should catch exception? Function match should catch exception? Apr 27, 2020
@stakx
Copy link
Contributor

stakx commented Apr 27, 2020

Seems like you really want to use .FirstOrDefault(), not .Single().

@stakx stakx closed this as completed Apr 27, 2020
@dawncold
Copy link
Author

Yes, there are some workaround expressions.

So we should be careful on match expression as it could raise exception?

@stakx
Copy link
Contributor

stakx commented Apr 27, 2020

So we should be careful on match expression as it could raise exception?

The LINQ .Single() operator is supposed to raise an exception when applied to a sequence with either zero items or more than one item, this has nothing to do with Moq. Why should matchers catch exceptions for you? That's not what they're for.

@dawncold
Copy link
Author

Well, I think m.Actions.Single() == Action.View has a better readability.

@stakx
Copy link
Contributor

stakx commented Apr 27, 2020

If you choose to use a method that may throw over a largely equivalent method that won't throw, fine... it's your code. But it is on you to deal with the consequence of that choice (exceptions being thrown).

It is not the Moq library's responsibility to randomly swallow user exceptions.

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

No branches or pull requests

2 participants