spring autowired mockito单元测试

本文介绍了一种在不触动DAO层的情况下对Spring Service层进行单元测试的方法。通过使用Mockito框架,我们可以模拟DAO层的行为,确保测试仅针对Service层的逻辑。文中详细展示了如何设置Mock对象以及编写具体的测试用例。

这两天在做spring service层的单元测试时,遇到了一些问题。service层会自动注入(autowired)dao层的interface,如何正常测试service层的逻辑,而不真正的触动dao层的代码,即不往数据库做实际操作,变成了一个需要解决的问题。首先,看一下我们service层的代码:

public interface RegisterUserService {	
	boolean insert(String passid,String msisdn,String email) throws SQLException;
	
}

@Service("registerUserService")
public class RegisterUserServiceImpl implements RegisterUserService {

    private Logger loggor = Logger.getLogger(getClass());

    

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PassidUserMapper passidUserMapper;

    @Autowired
    @Qualifier("redisService")
    private CacheService redisService;

    

    @Override
    @Transactional
    public boolean insert(String passid, String msisdn, String email)
            throws SQLException {
        if (StringUtils.isEmpty(passid))
            return false;

        User user = new User();
        if (!StringUtils.isEmpty(msisdn))
            user.setPhoneNo(msisdn);
        if (!StringUtils.isEmpty(email))
            user.setEmail(email);

        PassidUser passidUser = new PassidUser();
        String serverCode = ServerCodeConfig.serverCodeMap
                .get(PayUtil.ipAddress);
        if (StringUtils.isEmpty(serverCode)) {
            serverCode = "999";
        }
        String userid = serverCode + UIDUtil.next();
        passidUser.setUserid(userid);
        passidUser.setPassid(passid);

        user.setPassid(passid);
        user.setUserid(userid);
        Date date = new Date();
        user.setCreateTime(date);
        user.setUpdateTime(date);
        user.setDeleteFlag(0);

        /*if(loggor.isInfoEnabled()){
            loggor.info("passid:" + passid + "  userid:" + userid + "  msisdn:"
                    + msisdn + "  email:" + email);
        }*/

        int result = passidUserMapper.insert(passidUser);

        if (passidUserMapper.insert(passidUser) > 0
                && userMapper.insertSelective(user) > 0)
            redisService.set("passid:" + passid + ":userid", userid);
        else
            throw new SQLException("数据插入失败,数据回滚");

        return true;
    }

}

从代码中可以看到,service层的RegisterUserServiceImpl实现了interface RegisterUserService,在这个service中注入了userMapper,PassidUserMapper和RedisService,我们需要mock掉这三个autowired的真实行为,做spring相关的测试,我们选用的mockito进行,实现较为方便,在做spring mockito测试时,需要引入以下dependency :

       <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.10.19</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
	<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>

使用@InjectMock置入需要测试的RegisterUserServiceImpl,如下:

    @InjectMocks
    private RegisterUserService registerUserService = new RegisterUserServiceImpl();
对于需要mock掉的dao层的interface使用@Mock注入:

    @Mock
    private UserMapper userMapper;

    @Mock
    private PassidUserMapper passidUserMapper;

    @Mock
    private CacheService redisService;

注入后,需要对RsgisterUserService和UserMapper,PassidUserMapper,RedisService绑定:

MockitoAnnotations.initMocks(this);
同时,我们期望UserMapper和PassidMapper的功能得到想要的结果:

when(passidUserMapper.insert(any(PassidUser.class))).thenReturn(1);
when(userMapper.insertSelective(any(User.class))).thenReturn(1);
完整的单元测试代码如下:

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("file:src/main/resources/conf/springConfig.xml")
public class RegisterUserServiceImplTest {

    @InjectMocks
    private RegisterUserService registerUserService = new RegisterUserServiceImpl();

    @Mock
    private UserMapper userMapper;

    @Mock
    private PassidUserMapper passidUserMapper;

    @Mock
    private CacheService redisService;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        when(passidUserMapper.insert(any(PassidUser.class))).thenReturn(1);
        when(userMapper.insertSelective(any(User.class))).thenReturn(1);
    }

    @Test
    public void testInsert() throws Exception {
        String passid = "12344";
        String msisdn = "18867131210";
        String email = "test@test.cn";
        Assert.assertTrue(registerUserService.insert(passid, msisdn, email));

    }
}


如有问题,请联系wgy@live.cn,感谢!





### 如何使用Mockito进行Spring Controller单元测试 #### 准备工作 为了有效地对Spring控制器执行单元测试,需引入必要的依赖项。对于基于Maven的项目,在`pom.xml`文件中加入如下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>4.0.0</version> <scope>test</scope> </dependency> ``` 上述配置确保了JUnit和Mockito库被正确加载到项目的构建路径下。 #### 创建示例Controller类 定义一个简单的RESTful风格的控制器作为待测对象: ```java @RestController @RequestMapping("/api/users") public class UserController { private final UserService userService; @Autowired public UserController(UserService userService) { this.userService = userService; } @GetMapping("/{id}") public ResponseEntity<UserDTO> getUserById(@PathVariable Long id){ UserDTO userDto = userService.findUserById(id); return new ResponseEntity<>(userDto, HttpStatus.OK); } } ``` 此段代码展示了带有获取单个用户的HTTP GET请求映射的方法[^3]。 #### 编写单元测试案例 下面是一个针对上面创建的UserController编写的单元测试例子: ```java @RunWith(SpringRunner.class) @WebMvcTest(controllers = UserController.class) public class UserControllerTest { @Autowired private MockMvc mockMvc; @MockBean private UserService userService; @Test public void shouldReturnDefaultMessage() throws Exception { // Arrange Long userId = 1L; UserDTO mockUser = new UserDTO(); when(userService.findUserById(userId)).thenReturn(mockUser); // Act & Assert mockMvc.perform(get("/api/users/{id}", userId)) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE)); verify(userService).findUserById(userId)[^4]; } } ``` 这段测试代码通过`@WebMvcTest`注解来限定只加载Web层组件,并利用`MockMvc`实例发送模拟HTTP请求给目标端点;同时借助于`@MockBean`将UserService替换成由Mockito管理的虚拟实现以便控制其行为并验证交互情况。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值