简体   繁体   English

Moq上的扩展方法返回null

[英]Extension Method on Moq returns null

I try to test the result of some function where a call to an extension method is used. 我尝试测试一些函数的结果,其中使用了对扩展方法的调用。 This extension method is defined on an interface. 此扩展方法在接口上定义。 The test setup creates a mock of said interface. 测试设置创建所述界面的模拟。 For this mock two setups are configured. 对于此模拟,配置了两个设置。 When calling these setup function on the mocked interface implementation, everything works as intended. 在模拟的接口实现上调用这些设置函数时,一切都按预期工作。 (see TestMockSetupSourceClassA and TestMockSetupSourceClassB) But when these calls are made in the extension method the result is null. (请参阅TestMockSetupSourceClassA和TestMockSetupSourceClassB)但是当在扩展方法中进行这些调用时,结果为null。 (see TestDoClassStuff) (参见TestDoClassStuff)

I've set up a test project: https://github.com/sschauss/MoqExtensionMethodTest 我已经建立了一个测试项目: https//github.com/sschauss/MoqExtensionMethodTest

Extension 延期

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

Implementation 履行

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

Test 测试

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

The problem has to do with the Aggregate extension, its generic argument parameters and what you have Setup the mock to expect. 问题与Aggregate扩展,它的泛型参数参数以及模拟所期望的Setup有关。

The params of the extension method DoExtensionStuff is an object array so when calling the ` 扩展方法DoExtensionStuffparams是一个object数组,因此在调用`时

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

within the Aggregate delegate you are actually passing 在你正在传递的Aggregate代表中

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

which the mock was not configured to handle. 模拟没有配置处理。

After changing the _someInterfaceMock.Setup , in this particular case, explicitly to 更改_someInterfaceMock.Setup ,在此特定情况下,显式更改

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

All the tests in this scenario were able to be exercised to completion successfully. 此方案中的所有测试都能够成功完成。

The thing with Moq is that when a mock is not told explicitly what to expect it will return null by default for reference types. Moq的事情是,当模拟没有被明确告知期望它将默认为引用类型返回null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM