Java 单元测试中的模拟域实体

Java 单元测试中的模拟域实体,java,unit-testing,junit,mockito,Java,Unit Testing,Junit,Mockito,我有一个非常简单的问题:我一直在为一个具有上下文对象的命令对象编写一些单元测试。此上下文中有一些域实体 public class Context { private DomainEntity domainEntity1; private Dto dto1; // getters and setters go here... public boolean isDomainEntityValid() {

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

    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()

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

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

    doReturn(1L).when(domainEntity1).getId();
    doReturn("phil").when(domainEntity1).getName();
换句话说,必须定义getters方法的许多行为


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

我想你可能违反了这里的规定。我把它放在引号里,因为你不应该把它当作法律,而应该当作建议

您并没有给我们足够的上下文来告诉您应该具体更改什么(即:为什么命令需要id和名称?),但是还有另一个原则,我认为如果您按照这个原则更改代码,您的代码将更易于测试

(我想我可以对我的评论再详细一点)

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

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

如果你的命令逻辑是

DomainEntity domain = context.getDomainEntity();
domain.doSomething();
然后是的,您需要对域实体进行模拟

但是,如果您只是在上下文中工作,例如:

if (context.isDomainEntityValid()) {
    doSomething();
} else {
    doAnotherThing();
}
那么,模拟域实体就没有意义了

还有一件事需要注意,在mocking框架的帮助下,您可以根据SUT逻辑简单地执行stubing。您不需要对每个方法都进行存根


因此,如果您的命令只调用
domain.doSomething()
,只需存根这个方法即可。忘记
DomainEntity\anotherMethod()
DomainEntity\getId()

为了确保测试隔离,我可能会模拟与测试相关的每个依赖项。这将包括
上下文
域实体
Dto
和任何其他相关依赖项。这一切都取决于命令内部的逻辑。如果它确实获得了domainEntity并对其进行了处理,那么您必须模拟domainEntity。