2

我有一个非常简单的问题:我一直在为具有 Context 对象的命令对象编写一些单元测试。这个上下文里面有一些领域实体。

    public class Context { 
          private DomainEntity domainEntity1;
          private Dto dto1;

          // getters and setters go here...

          public boolean isDomainEntityValid() {
              // a little bit of logic goes here
          }
    }

    public class Command {

          public void execute(Context context) { 
                // do its logic in here
          }
    }

DTO 和 DomainEntity 只有 setter 和 getter 以及非常简单的验证方法(例如isFirstNameValid())。

Context 对象中确实有逻辑——毕竟,它检查上下文是否一致,上下文是否完整,等等。

在对命令对象进行单元测试时,我很清楚应该模拟出上下文 - 但是实体和 dto 呢?我应该嘲笑他们吗?如果是这样,我将不得不做很多像下面这样的代码

    doReturn(1L).when(domainEntity1).getId();
    doReturn("phil").when(domainEntity1).getName();

换句话说,必须定义 getters 方法的许多行为。

所以,底线:我应该在对对象进行单元测试时模拟域实体和 DTO 吗?

4

2 回答 2

2

我认为您可能在这里违反了得墨忒耳的“法则”。我把它放在引号中是因为你不应该将此作为法律,而应作为建议。

您并没有真正给我们足够的上下文来告诉您应该具体更改什么(即:为什么命令需要 id 和名称?),但是还有另一个原则叫做告诉,不要问和我想想如果你改变你的代码来遵循它,你的代码将变得更容易测试。

于 2013-01-18T01:30:18.440 回答
0

(我想我可以在我的评论中详细说明)

您是否需要进行模拟等都取决于您的被测系统(SUT,在本例中为您的命令)中的逻辑。

模拟/存根的整个想法是我们对 SUT 的测试不依赖于其他实际代码。因此我们编写了适合在测试中使用的模拟/存根,因此测试的有效性仅取决于 SUT,而不取决于其他实际代码(当然,假设您的模拟/存根编写正确,但这通常不是问题由于其简单性)

因此,如果您的 Command 逻辑类似于

DomainEntity domain = context.getDomainEntity();
domain.doSomething();

那么是的,您需要为您的域实体进行模拟。

但是,如果您只是针对上下文工作,例如:

if (context.isDomainEntityValid()) {
    doSomething();
} else {
    doAnotherThing();
}

那么模拟域实体就没有意义了。

还有一点需要注意,借助模拟框架,您可以根据您的 SUT 逻辑简单地进行存根。你不需要为每个方法做存根。

因此,如果您的 Command 仅调用domain.doSomething(),则只需存根此方法。忘了DomainEntity#anotherMethod() DomainEntity#getId()

于 2013-01-18T03:25:11.150 回答