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

Mock<T>.Raise doesn't work although InternalsVisibleTo is set #231

Closed
urasandesu opened this issue Dec 23, 2015 · 1 comment
Closed

Mock<T>.Raise doesn't work although InternalsVisibleTo is set #231

urasandesu opened this issue Dec 23, 2015 · 1 comment

Comments

@urasandesu
Copy link
Contributor

Mock<T>.Raise throws ArgumentException against an internal event even if InternalsVisibleTo attribute is set. Here is the product code:

class Class1
{
    internal virtual event EventHandler Foo;
}
[assembly: InternalsVisibleTo("ClassLibrary29Test")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

The test code is like this:

[TestFixture]
class Class1Test
{
    [Test]
    public void Foo_should_be_raised_through_Moq()
    {
        // Arrange
        var called = false;
        var m = new Mock<Class1>();
        m.Object.Foo += (sender, e) => { called = true; };

        // Act
        m.Raise(_ => _.Foo += null, new EventArgs());

        // Assert
        Assert.IsTrue(called);
    }
}

When running this test, I got the following failed result:

PS ClassLibrary29>  .\packages\NUnit.Runners.2.6.4\tools\nunit-console.exe .\ClassLibrary29Test\bin\Debug\ClassLibrary29Test.dll
NUnit-Console version 2.6.4.14350
Copyright (C) 2002-2012 Charlie Poole.
Copyright (C) 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov.
Copyright (C) 2000-2002 Philip Craig.
All Rights Reserved.

Runtime Environment - 
   OS Version: Microsoft Windows NT 6.2.9200.0
  CLR Version: 2.0.50727.8009 ( Net 3.5 )

ProcessModel: Default    DomainUsage: Single
Execution Runtime: net-3.5
.F
Tests run: 1, Errors: 1, Failures: 0, Inconclusive: 0, Time: 0.731321957049282 seconds
  Not run: 0, Invalid: 0, Ignored: 0, Skipped: 0

Errors and Failures:
1) Test Error : ClassLibrary29Test.Class1Test.Foo_should_be_raised_through_Moq
   System.ArgumentException : Could not locate event for attach or detach method Void add_Foo(System.EventHandler).
   場所 Moq.Extensions.GetEvent[TMock](Action`1 eventExpression, TMock mock)
   場所 Moq.Mock`1.Raise(Action`1 eventExpression, EventArgs args)
   場所 ClassLibrary29Test.Class1Test.Foo_should_be_raised_through_Moq() 場所 c:\Users\Akira\Documents\Visual Studio 2013\Projects\ClassLibrary29\ClassLibrary29Test\Class1Test.cs:行 20


PS ClassLibrary29>  

What should I do to succeed this test?
For your information, I placed the complete sln in my Google Drive.

@stakx
Copy link
Contributor

stakx commented Jun 22, 2017

@urasandesu:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] makes internals visible to DynamicProxy, which is the library Moq is based on. Thanks to this, you can create a mock without any exceptions happening.

[assembly: InternalsVisibleTo("ClassLibrary29Test")] makes internals visible to the compiler, which is why you can compile ClassLibrary29Test without any errors.

However, none of these do anything for Moq itself. While Moq uses DynamicProxy, it is also more than DynamicProxy. Moq generally only looks for publicly visible methods and for interface methods. Since you have declared your event as internal, Moq simply won't find it (even though it is there in the proxy type generated by DynamicProxy), which is why you receive the runtime error.


If Moq's Moq.Protected namespace offered a method such that you could do mock.Protected().Raise(…) instead of mock.Raise(…), that might have been an option; but Moq doesn't currently have that functionality.

As a workaround, you could also an an internal method to Class1 that raises the event:

partial class Class1
{
    internal void RaiseFoo()
    {
        Foo?.Invoke(this, EventArgs.Empty);
    }
}

Then in your test, you replace m.Raise(_ => _.Foo += null, …) with m.Object.RaiseFoo();.

Not ideal, I know, but testing internals can get messy quite quickly.

@stakx stakx closed this as completed Jun 27, 2017
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