如何在服务层模拟方法

Posted

技术标签:

【中文标题】如何在服务层模拟方法【英文标题】:How to mock a method in Service layer 【发布时间】:2021-12-10 19:08:40 【问题描述】:

在对服务层的每个方法进行单元测试时,我遇到了以下场景,我不知道如何测试:

public class UserServiceImpl

    @Autowired
    UserRepository userRepository;

    public void abc()
        xyz(obj);
    

    private void xyz()
        userRepository.save(obj);
    

我要测试的是abc() 方法。在该方法中,它调用xyz(),这是一个使用userRepository 依赖项的PRIVATE 方法。那么,当我为abc() 方法创建单元测试时,我是否需要关注xyz() 方法,因为它使用了依赖项?如果是,我需要遵循哪些步骤?

【问题讨论】:

您需要使用 UserRepository 的模拟版本来实例化 UserServiceImpl 嗨@slauth,我也有同样的想法。但是这样做可以吗? 当然……你为什么认为这样不行? @NisalPubudu - 如果您发现其中任何一个有帮助,请选择/投票赞成 【参考方案1】:

正如您所写,您需要处理xyz() 方法及其对userRepository 的调用。你需要模拟userRepository如下:

@ExtendWith(MockitoExtension.class)
public class UserServiceImplTest 

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    public UserServiceImpl userService;

    @BeforeEach
    public void setUp() throws Exception 
        // Mock UserRepository behaviour
        doReturn(//return value).when(this.userRepository).save(any());
    

    // Your tests here


【讨论】:

@Nisal Pubudu 我的回答有帮助吗? 是的@João,但我仍然没有足够的代表来支持答案。一旦我有足够的,我会赞成它。谢谢。【参考方案2】:

由于这是一个 void 方法,您要做的是验证依赖项的 save 方法是否已使用参数 obj 仅调用过一次。您可以使用Mockito 之类的东西来做到这一点。你的单元测试看起来像这样:

    @Mock
    private UserRepository mockUserRepository;

    @InjectMocks
    private UserServiceImpl sut;

    @Test
    public void abc_savesObject() 
        // Arrange
        ...

        // Act
        sut.abc();

        // Assert
        verify(mockUserRepository,times(1)).save(obj);
    

一些有用的链接:

https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#4 https://www.baeldung.com/mockito-verify

【讨论】:

嗨@Ivan,如果我按照上述步骤操作,userRepository.save() 方法是否仍将数据保留在实际数据库中? @NisalPubudu 在您使用存储库的模拟版本时,不会保留任何数据。 @Mock 注解会创建一个依赖项的模拟实例。 @InjectMocks 注释将模拟实例作为依赖项注入到您正在单元测试的类中,允许您验证模拟方法使用特定参数调用的次数。阅读 Mockito javadoc 以获取更多信息会很有用:javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/… 谢谢@Ivan

以上是关于如何在服务层模拟方法的主要内容,如果未能解决你的问题,请参考以下文章

动作过滤器:如何调用服务层和异步方法

实现服务层方法的指南

三层交换机怎么配置才能使不同网段的PC访问服务器

java ee EJB中的服务层和dao层

如何在 Spring Junit 中创建会话

在Java中测试服务层中的void方法[重复]