Moq - 设置通用返回类型

问题描述 投票:0回答:3

如何在 Moq 中设置通用返回类型?

我有以下界面:

public interface IFoo
{
   T Bar<T>();
}

现在我想设置

Bar<T>()
在测试中工作

var foo = new Mock<IFoo>();
foo.Setup(x => x.Bar<It.IsAnyType>()).Returns(new Mock<???>().Object);

我如何填写

???
,或者如果不可能,那么我如何返回通用模拟?

有数百种类型,我试图避免嘲笑它们。 如果调用对于任何类型返回 null,则测试会中断(因为代码会抛出异常),遗憾的是,这是默认的非模拟行为。

c# .net moq
3个回答
1
投票

如果

T
是引用类型,即

public interface IFoo {
    T Bar<T>() where T : class;
}

然后创建一个苗条的模拟会更容易

public class MockFoo : IFoo {
    private MockFoo() {

    }

    public T Bar<T>() where T : class => Mock.Of<T>();

    public static IFoo New() => new MockFoo();
}

可以在安排测试时进行初始化,并使用最小起订量来模拟

Bar

的输出
//Arrange
IFoo foo =  MockFoo.New();

//...

1
投票

尝试使用这个

Returns
重载:
IReturnsResult<TMock> Returns(InvocationFunc valueFunction);

设置:

 factory.Setup(m => m.Create<It.IsAnyType>())
        .Returns(new InvocationFunc(invocation =>
                 {
                     var typeArgument = invocation.Method.GetGenericArguments()[0];
                     return Activator.CreateInstance(typeArgument);
                 });

致电:

 var something = factory.Object.Create<Something>();

0
投票

如前所述,创建模拟需要引用类型:

public interface IFoo
{
    T Bar<T>() where T : class;
}

现在,可以使用反射创建

Mock<T>
。 这确实很难看,但当接口作为
T
传递时,或者当使用的类没有默认构造函数时,它也可以工作。

var fooMock = new Mock<IFoo>();
fooMock
    .Setup(foo => foo.Bar<It.IsAnyType>())
    .Returns(new InvocationFunc(call =>
    {
        // create type Mock<T> with the type passed to Bar<T>
        var typeArg = call.Method.GetGenericArguments()[0];
        var mockType = typeof(Mock<>).MakeGenericType(typeArg);
        var mock = Activator.CreateInstance(mockType);

        // find "Object" property, call get
        var objectProperty = mockType.GetProperty(nameof(Mock.Object), typeArg);
        return objectProperty.GetValue(mock);
    }));
© www.soinside.com 2019 - 2024. All rights reserved.