Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force moq to call the constructor?

Tags:

c#

.net

moq

I have a unit test to verify that an object (say Foo) will call certain method (say Bar) when an event is fired with certain eventArgs. To mock the said method, I use virtual and stub the Foo class

Mock<Foo> stubbedFoo = new Mock<Foo>(mockEventProvider);

mockEventProvider.Raise( x => x.MyEvent += null, myEventArgs ) //fire the event
stubbedFoo.Verify(foo => foo.Bar()); verify Bar is called as a result

However, the above failed, Bar will not be called, apparently because the Foo object is not event constructed. However if I add a line like below:

Mock<Foo> stubbedFoo = new Mock<Foo>(mockEventProvider);
var workAround = stubbedFoo.Object //adding this workaround will work
mockEventProvider.Raise( x => x.MyEvent += null, myEventArgs ) //fire the event
stubbedFoo.Verify(foo => foo.Bar()); verify Bar is called as a result

It will work, because calling get on .Object apparently forces mock to construct the object. Is there a more elegant solution than adding this line ?

like image 629
Louis Rhys Avatar asked Aug 31 '12 10:08

Louis Rhys


People also ask

How do you mock a method in MOQ?

First, we instantiate the FakeDbArticleMock class and indicate which setup we want to use for this test. Then, it is necessary to instantiate the repository we want to test and inject the mock instance into it. Finally, we call the method we are testing and assert the results.

What does MOQ CallBase do?

CallBase , when initialized during a mock construction, is used to specify whether the base class virtual implementation will be invoked for mocked dependencies if no setup is matched. The default value is false . This is useful when mocking HTML/web controls of the System.

What does MOQ verify do?

Verifies that all verifiable expectations have been met.

How do you create a object in MOQ?

Simpler mock objects, using MoqRight-click on the TestEngine project (the one we want to add Moq to). Select “Manage NuGet Packages…” In the NuGet tab, select “Browse” and search for “Moq” – the library we want to add. There are several add-on libraries that make it easier to use Moq in different types of programs.


1 Answers

I don't think you can. I checked out the moq source and poked through it and it doesn't look like the proxy intercepter from castle is actually created until you call .Object. Look at this trace:

public object Object
{
    get { return this.GetObject(); }
}

private object GetObject()
{
    var value = this.OnGetObject();
    this.isInitialized = true;
    return value;
}

Followed by

protected override object OnGetObject()
{
    if (this.instance == null)
    {
        this.InitializeInstance();
    }

    return this.instance;
}

Which does this:

private void InitializeInstance()
{
    PexProtector.Invoke(() =>
    {
        this.instance = proxyFactory.CreateProxy<T>(
            this.Interceptor,
            this.ImplementedInterfaces.ToArray(),
            this.constructorArguments);
    });
}

ProxyFactory actually creates the object and wraps it in a proxy

public T CreateProxy<T>(ICallInterceptor interceptor, Type[] interfaces, object[] arguments)
{
    var mockType = typeof(T);

    if (mockType.IsInterface)
    {
        return (T)generator.CreateInterfaceProxyWithoutTarget(mockType, interfaces, new Interceptor(interceptor));
    }

    try
    {
        return (T)generator.CreateClassProxy(mockType, interfaces, new ProxyGenerationOptions(), arguments, new Interceptor(interceptor));
    }
    catch (TypeLoadException e)
    {
        throw new ArgumentException(Resources.InvalidMockClass, e);
    }
    catch (MissingMethodException e)
    {
        throw new ArgumentException(Resources.ConstructorNotFound, e);
    }
}
like image 59
devshorts Avatar answered Oct 02 '22 09:10

devshorts