JUnit测试中的模拟超级返回值

33qvvth1  于 2023-06-23  发布在  其他
关注(0)|答案(2)|浏览(127)

我正在扩展一个类并重写一个方法。现在我尝试为CustomerUserService类创建Junit测试,代码如下

public class CustomerUserService extends DefaultUserService implements SlpUserService {

    @Override
    public User getUserForID(final String userId) {

        User user = super.getUserForUID(userId);
      

        //work with user object

如何模拟super.getUserForUID(userId)的返回值;?
我想测试CustomerUserService#getUserForID中的逻辑,并试图模拟super.getUserForUID(userId);调用来返回一些User对象,但是它总是调用真实的的超级方法并执行那里的逻辑。
如何模拟super.getUserForUID(userId)的返回值;?
我在Junit测试中声明CustomerUserService为spy:

@Spy
    private CustomerUserService customerUserService;
mbjcgjjk

mbjcgjjk1#

我从来没有弄清楚如何嘲笑超级;我不是说这是不可能的,只是说我从来没有做过。
相反,我确定了super的依赖关系并模拟了它们。例如,在您的示例中,您可能希望模拟UserForUUID从中读取的存储库(假设它从存储库中读取)。

vktxenjb

vktxenjb2#

这就是为什么你应该使用favor composition over inheritance的原因之一。你设计它的方式,你不应该模拟超级调用,因为它是测试类行为的一部分。
与其扩展现有的用户服务,不如将其用作数据源,然后可以模拟它。
比如说

public class CustomerUserService implements SlpUserService {
  private final SlpUserService sourceService;
  public CustomerUserService(SlpUserService source) {
    sourceService = source; // rather than super(source)
  }

  @Override
  public User getUserForID(final String userId) {
    User user = sourceService.getUserForUID(userId);
    // work with user
  }
}

然后,您可以轻松地模拟DefaultUserService--事实上,您可以传入任何SlpUserService实现,使其更加灵活。
当然,您可以始终过度工程化,也可以提取“使用用户对象”部分。

class UserProcessor implements SlpUserService {
  private final SlpUserService sourceService;
  private final Consumer<User> processor;

  // constructor tbd
  @Override
  public User getUserForID(final String userId) {
    User user = sourceService.getUserForUID(userId);
    processor.accept(user);
    return user;
  }
}

然后你只需要验证1。将传入的用户服务用作数据源; 2.它提供的用户在返回它之后被传递给消费者进行处理。这样,您就可以分别对具体的用户服务和实际处理部分进行单元测试。

相关问题