void返回方法是否会将其参数的状态更改为反模式?

时间:2013-03-12 13:47:30

标签: unit-testing mocking anti-patterns

返回void的方法是否会更改其参数的状态(即提供隐藏或隐式返回值)通常是一种不好的做法?

我发现它们很难嘲笑,这表明它们可能是一个糟糕设计的标志。

有哪些模式可以避免它们?

一个非常人为的例子:

public interface IMapper
{
    void Map(SourceObject source, TargetObject target);
}

public class ClassUnderTest
{
    private IMapper _mapper;

    public ClassUnderTest(IMapper mapper)
    {
        _mapper = mapper;
    }

    public int SomeOperation()
    {
        var source = new SourceObject();
        var target = new TargetObject();

        _mapper.Map(source, target);

        return target.SomeMappedValue;
    }
}

2 个答案:

答案 0 :(得分:1)

如果您执行此操作,您的代码将更容易测试:

public interface IMapper
{
    TargetObject Map(SourceObject source);
}

public class ClassUnderTest
{
    private IMapper _mapper;

    public ClassUnderTest(IMapper mapper)
    {
        _mapper = mapper;
    }

    public int SomeOperation(SourceObject source )
    {
        var target =  _mapper.Map(source, target);
        return target.SomeMappedValue;
    }
}

您现在可以分别测试Map opperation和SomeOperation。问题是你idd改变一个对象的状态,这使得很难提供一个存根进行测试。返回新对象时,您可以返回目标的测试存根并测试调用方法。

答案 1 :(得分:1)

在某种程度上是的。

您所描述的是典型的副作用。副作用使程序难以理解,因为您需要理解的信息不包含在调用堆栈中。您需要其他信息,即在订单之前(以及以什么方式)调用的方法。

解决方案是编程没有副作用。这意味着您不需要更改变量,字段或任何内容。相反,你会返回通常会改变的新版本。

这是函数式编程的基本原理。

当然,这种编程方式有其自身的挑战。只考虑I / O.