如何强制moq调用构造函数?

时间:2012-08-31 10:55:59

标签: c# .net moq

我有一个单元测试来验证一个对象(比如Foo)在使用某些eventArgs触发事件时会调用某个方法(比如Bar)。为了模拟所述方法,我使用虚拟和存根Foo

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

但是,上面的失败,Bar不会被调用,显然是因为Foo对象不是构造事件的。但是,如果我添加如下所示的行:

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

它会起作用,因为调用get on .Object显然会强制mock来构造对象。有没有比添加这条线更优雅的解决方案?

1 个答案:

答案 0 :(得分:1)

我认为你不能。我查看了moq source并通过它进行了搜索,看起来castle中的代理拦截器实际上并未创建,直到您调用.Object。看看这条痕迹:

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

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

其次是

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

    return this.instance;
}

这是做什么的:

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

ProxyFactory实际上创建了对象并将其包装在代理

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);
    }
}