单元测试中的模拟域实体

时间:2013-01-18 00:18:41

标签: java unit-testing junit mockito

我有一个非常简单的问题:我一直在为一个具有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();

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

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

2 个答案:

答案 0 :(得分:2)

我认为你可能在这里违反了"Law" of Demeter。我把它放在引号中是因为你不应该遵循这个法律作为建议。

你并没有真正给我们足够的背景来告诉你应该具体改变什么(即:为什么命令需要id和名字?),但是还有其他原则名为Tell, Don't Ask,我认为如果您更改代码,您的代码将变得更容易测试。

答案 1 :(得分: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()