[Springboot 单元测试笔记] - Mock 和 spy的使用

Springboot单元测试 - 依赖类mock测试

通常单元测试中,我们会隔离依赖对于测试类的影响,也就是假设所有依赖的一定会输出理想结果,在测试中可以通过Mock方法来确保输出结果,这也就引入另一个测试框架Mockito。

Mockito框架的作用就是模拟接口功能,并不运行模拟接口的实际逻辑,而是直接输出一个假定结果。

Mockito常见注释及方法

@Mock被注释的对象会作为Mock对象
@InjectMocks被注释的对象依赖于@Mock的对象,通常是测试对象
when(<MockObject>.<method>).thenReturn()对@Mock的对象进行模拟输出
doThrow(<Exception>).when(<mockObject>).<Method>对Mock的对象模拟抛出一个异常
spy()也是建立一个模拟对象,但可以

待测试类 - AController

public class AController {

    @Autowired
    MongoService mongoService;

    public boolean testBean() {
        boolean res = mongoService.testMethod2(4);
        return res;
    }

}

依赖类 - MongoService

@Service
public class MongoService {

    public void output() {
        System.out.println("This is a bean!!");
    }

    public boolean testMethod1(int num) {
        return num > 0;
    }

    public boolean testMethod2(int num) {
        int val = getVal();
        return val > num;
    }

    private int getVal() {
        return 2;
    }
}

Mockito测试类 - RunWith需要运行MockitoJUnitRunner.class才能使用Mockito相关注解

方法1: 使用@Mock,更为简洁只需加入注解就可以mock对应成员变量 (该成员变量可以是非依赖注入)

@RunWith(MockitoJUnitRunner.class)
public class MockTest {

    @Mock
    MongoService mongoService;

    @InjectMocks
    AController aController;

    @Test
    public void testMock1() {
        when(mongoService.testMethod2(Mockito.anyInt())).thenReturn(true);
        Assert.assertEquals(aController.testBean(), true);
    }

    @Test(expected = Exception.class)
    public void testMock2() {
        doThrow(Exception.class).when(mongoService).testMethod2(Mockito.anyInt());
        aController.testBean();
    }
}

方法2: 使用Mock函数

public class MockTest {

    MongoService mongoService;

    AController aController;

    @BeforeEach
    public void init() {
        mongoService = Mock(MongoService.class);
        aController = new AController();
        /* 假设 AController class 中有setter用于加载mongoService */
        aController.setMongoService(mongoService);
        
    }

    @Test
    public void testMock1() {
        when(mongoService.testMethod2(Mockito.anyInt())).thenReturn(true);
        Assert.assertEquals(aController.testBean(), true);
    }

    @Test(expected = Exception.class)
    public void testMock2() {
        doThrow(Exception.class).when(mongoService).testMethod2(Mockito.anyInt());
        aController.testBean();
    }
}

 

@Mock 和 @Spy区别

上面两种注释都是建立一个模拟对象,但是区别是@Mock注释的对象是完全虚拟,不能调用这个Mock对象的任何方法,只能通过when().thenReturn() 来进行模拟输出;但是@Spy是建立一个真实的Mock对象,可以调用对象中任何方法也可以模拟某些方法的输出。@Spy大大增加了测试的自由度,比如如果某个测试类你只想模拟某个方法但是想要某些方法的真实输出,这是@Spy就可以解决这个问题。

举例 - 模拟MongoService其中一个方法,并测试另一个方法真实输出

    @Spy
    MongoService mongoServiceSpy;

    @Test
    public void testSpy() {
        /** 模拟MongoService中 getVal并测试testMethod2*/
        when(mongoServiceSpy.getVal()).thenReturn(3);
        Assert.assertEquals(mongoServiceSpy.testMethod2(2), true);
    }

Reference

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot的JUnit单元测试中,可以使用Mockito来创建mock数据,Mockito是一个流行的Java测试框架,可以模拟对象的行为和方法,以便更容易地测试代码。 下面是一个简单的示例,演示如何在Spring Boot的JUnit测试中使用Mockito创建mock数据: 假设有一个UserService类,其中有一个getUserById()方法,可以通过用户ID获取用户对象。 ```java @Service public class UserService { @Autowired private UserRepository userRepository; public User getUserById(Long id) { return userRepository.findById(id); } } ``` 现在我们想测试getUserById()方法,但是我们不想依赖于实际的数据库和UserRepository对象,而是想使用mock数据来测试它。我们可以使用Mockito来创建mock UserRepository对象,并在测试中使用它。 ```java @RunWith(SpringRunner.class) @SpringBootTest public class UserServiceTest { @Autowired private UserService userService; @MockBean private UserRepository userRepository; @Test public void testGetUserById() { User user = new User(); user.setId(1L); user.setName("Alice"); Mockito.when(userRepository.findById(1L)).thenReturn(user); User result = userService.getUserById(1L); Assert.assertEquals("Alice", result.getName()); } } ``` 在这个示例中,我们使用@MockBean注解创建了一个mock的UserRepository对象,并使用Mockito.when()方法来告诉Mockito当findById()方法被调用时应该返回什么对象。 然后,我们调用UserService的getUserById()方法,它将使用我们创建的mock对象而不是实际的数据库和UserRepository对象。 最后,我们使用JUnit的Assert.assertEquals()方法来验证getUserById()方法返回的用户对象是否符合预期。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值