【问题标题】:Extension Method on Moq returns nullMoq 上的扩展方法返回 null
【发布时间】:2023-03-05 16:03:01
【问题描述】:

我尝试测试一些调用扩展方法的函数的结果。这个扩展方法是在一个接口上定义的。测试设置创建了所述接口的模拟。对于这个模拟,配置了两个设置。在模拟接口实现上调用这些设置函数时,一切都按预期工作。 (请参阅 TestMockSetupSourceClassA 和 TestMockSetupSourceClassB)但是当在扩展方法中进行这些调用时,结果为空。 (参见 TestDoClassStuff)

我已经建立了一个测试项目:https://github.com/sschauss/MoqExtensionMethodTest

扩展

public static class ExtensionClass
{
    public static TResult DoExtensionStuff<TResult>(this ISomeInterface someInterface, object initialObject,
        params object[] objects)
    {
        var result = someInterface.DoInterfaceStuff<TResult>(initialObject);
        return objects.Aggregate(result, (agg, cur) => someInterface.DoInterfaceStuff(cur, agg));
    }
}

实施

public class SomeClass
{
    private readonly ISomeInterface _someInterface;

    public SomeClass(ISomeInterface someInterface)
    {
        _someInterface = someInterface;
    }

    public TargetClass DoClassStuff(SourceClassA sourceClassA, SourceClassB sourceClassB)
    {
        return _someInterface.DoExtensionStuff<TargetClass>(sourceClassA, sourceClassB);
    }
}

测试

public class UnitTest
{
    private readonly SomeClass _sut;
    private readonly SourceClassA _sourceA;
    private readonly SourceClassB _sourceB;
    private readonly TargetClass _target;
    private readonly Mock<ISomeInterface> _someInterfaceMock;

    public UnitTest()
    {
        _sourceA = new SourceClassA
        {
            Integer = 1
        };
        _sourceB = new SourceClassB
        {
            String = "stringB"
        };
        _target = new TargetClass
        {
            Integer = 2,
            String = "stringT"
        };
        _someInterfaceMock = new Mock<ISomeInterface>();
        _someInterfaceMock.Setup(m => m.DoInterfaceStuff<TargetClass>(_sourceA)).Returns(_target);
        _someInterfaceMock.Setup(m => m.DoInterfaceStuff(_sourceB, _target)).Returns(_target);
        _sut = new SomeClass(_someInterfaceMock.Object);
    }

    [Fact]
    public void TestDoClassStuff()
    {
        var result = _sut.DoClassStuff(_sourceA, _sourceB);

        result.Should().BeEquivalentTo(_target);
    }

    [Fact]
    public void TestMockSetupSourceClassA()
    {
        var result = _someInterfaceMock.Object.DoInterfaceStuff<TargetClass>(_sourceA);

        result.Should().BeEquivalentTo(_target);
    }

    [Fact]
    public void TestMockSetupSourceClassB()
    {
        var result = _someInterfaceMock.Object.DoInterfaceStuff(_sourceB, _target);

        result.Should().BeEquivalentTo(_target);
    }
}

【问题讨论】:

    标签: c# unit-testing .net-core moq xunit


    【解决方案1】:

    问题与Aggregate 扩展、它的通用参数参数以及您对Setup 的模拟有关。

    扩展方法DoExtensionStuff的params是一个object数组所以当调用`

    T2 DoInterfaceStuff<T1, T2>(T1 parameter1, T2 parameter2)
    

    在Aggregate 代表中,您实际上是在传递

     (TResult agg, object cur) => someInterface.DoInterfaceStuff<object,TResult>(cur, agg)
    

    模拟未配置为处理的。

    更改_someInterfaceMock.Setup 后,在这种特殊情况下,显式更改为

     _someInterfaceMock
        .Setup(m => m.DoInterfaceStuff<object, TargetClass>(_sourceB, _target))
        .Returns(_target);
    

    此场景中的所有测试都能够成功完成。

    Moq 的问题是,如果没有明确地告诉 mock 会发生什么,默认情况下它会为引用类型返回 null。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-19
      • 1970-01-01
      • 2021-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多