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

Changed behavior with explicit interface implementations #133

Closed
magnusbakken opened this issue Sep 30, 2014 · 2 comments
Closed

Changed behavior with explicit interface implementations #133

magnusbakken opened this issue Sep 30, 2014 · 2 comments
Labels

Comments

@magnusbakken
Copy link

I think I've discovered a change in behavior from version 4.2.1402 to 4.2.1408. The following test used to pass but no longer does:

namespace MoqRegression
{
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Moq;

    public class C : I
    {
        public virtual void A()
        {
        }

        void I.B()
        {
            this.A();
        }
    }

    public interface I
    {
        void B();
    }

    [TestClass]
    public class TestClass
    {
        [TestMethod]
        public void TestMethod()
        {
            var target = new Mock<C>();
            ((I)target.Object).B();
            target.Verify(x => x.A());
        }
    }
}

The test failure message is as follows:

Test Name: TestMethod
Test FullName: MoqRegression.TestClass.TestMethod
Test Source: C:\Users\magbakke\documents\visual studio 2013\Projects\MoqRegression\MoqRegression\Program.cs : line 28
Test Outcome: Failed
Test Duration: 0:00:00,1041002

Result Message:
Test method MoqRegression.TestClass.TestMethod threw exception:
Moq.MockException:
Expected invocation on the mock at least once, but was never performed: x => x.A()
No setups configured.

Performed invocations:
I.B()
Result StackTrace:
at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable1 setups, IEnumerable1 actualCalls, Expression expression, Times times, Int32 callCount)
at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times)
at Moq.Mock.Verify[T](Mock`1 mock, Expression1 expression, Times times, String failMessage) at Moq.Mock1.Verify(Expression`1 expression)
at MoqRegression.TestClass.TestMethod() in C:\Users\magbakke\documents\visual studio 2013\Projects\MoqRegression\MoqRegression\Program.cs:line 31

From debugging it seems like the difference is simply that in 4.2.1402, the line ((I)target.Object).B() does in fact call the implementation of B on C, as if the CallBase property on the mock were set to true, while in 4.2.1408 it doesn't get called. It also only gets called in 4.2.1402 when B is defined as an explicit interface implementation. In other words, if you change the signature to public void B() the test fails on the old version as well.

The test passes in both versions if I set CallBase to true.

Is it just an accident that this ever worked? I haven't figured out which particular commit changed the behavior yet, so I can't be sure.

@kzu
Copy link
Member

kzu commented Oct 29, 2014

It was definitely an accident that it ever worked ;)

/kzu from mobile
On Sep 30, 2014 9:10 AM, "magnusbakken" [email protected] wrote:

I think I've discovered a change in behavior from version 4.2.1402 to
4.2.1408. The following test used to pass but no longer does:

namespace MoqRegression
{
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

public class C : I
{
    public virtual void A()
    {
    }

    void I.B()
    {
        this.A();
    }
}

public interface I
{
    void B();
}

[TestClass]
public class TestClass
{
    [TestMethod]
    public void TestMethod()
    {
        var target = new Mock<C>();
        ((I)target.Object).B();
        target.Verify(x => x.A());
    }
}

}

The test failure message is as follows:

Test Name: TestMethod
Test FullName: MoqRegression.TestClass.TestMethod
Test Source: C:\Users\magbakke\documents\visual studio
2013\Projects\MoqRegression\MoqRegression\Program.cs : line 28
Test Outcome: Failed
Test Duration: 0:00:00,1041002

Result Message:

Test method MoqRegression.TestClass.TestMethod threw exception:
Moq.MockException:
Expected invocation on the mock at least once, but was never performed: x
=> x.A()
No setups configured.

Performed invocations:
I.B()
Result StackTrace:

at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable1
setups, IEnumerable1 actualCalls, Expression expression, Times times,
Int32 callCount)
at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall
expected, Expression expression, Times times)
at Moq.Mock.VerifyT
at Moq.Mock1.Verify(Expression1 expression)
at MoqRegression.TestClass.TestMethod() in
C:\Users\magbakke\documents\visual studio
2013\Projects\MoqRegression\MoqRegression\Program.cs:line 31

From debugging it seems like the difference is simply that in 4.2.1402,
the line ((I)target.Object).B() does in fact call the implementation of B
on C, as if the CallBase property on the mock were set to true, while in
4.2.1408 it doesn't get called. It also only gets called in 4.2.1402 when
B is defined as an explicit interface implementation. In other words, if
you change the signature to public void B() the test fails on the old
version as well.

The test passes in both versions if I set CallBase to true.

Is it just an accident that this ever worked? I haven't figured out which
particular commit changed the behavior yet, so I can't be sure.

Reply to this email directly or view it on GitHub
#133.

@stakx
Copy link
Contributor

stakx commented Jun 20, 2017

This is fixed in Moq 4.7.58.

@stakx stakx closed this as completed Jun 20, 2017
@stakx stakx added the bug label Jun 20, 2017
@devlooped devlooped locked and limited conversation to collaborators Sep 8, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants