使用mockito配置spring-data-jpa业务逻辑层的测试

如果要对service层进行mock测试,首先需要解决的就是autowired的问题,因为在使用的时候,框架会帮我们解决对象创建的问题,所以我们一般不会预留构造函数,这就给我们mock带来了一点麻烦。还好,mockito提供了解决方案,就是利用@InjectMocks注解:

@InjectMocks - Instantiates testing object instance and tries to inject fields annotated with @Mock or @Spy into private fields of testing object

这个注解会把所有用@Mock@Spy注解的属性注入到被标记的属性里。比如:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest extends AbstractJUnit4SpringContextTests {
    @Mock
    private UserRegistry userDao;

    @InjectMocks
    private UserService userService;
}

@Service
public class UserService {
    @Autowired
    private UserRegistry userDao;
}

这里就会把UserRegistry和LoginLogRegistry注入到UserService里。从名字里也可以看出,这两个是DAO层的内容,是在service里被autowired的。如果这里报错的话,之前看到有人说,可以加一个这个,用来初始化mock(虽然我这里不用):

@Before
public void initMocks() {
    MockitoAnnotations.initMocks(this);
}

mock完之后就是测试业务逻辑了。假如service里有这样的一个逻辑,判断是否存在这样的一个用户:

@Service
public class UserService {
    @Autowired
    private UserRegistry userDao;

    public boolean hasMatchUser(String userName, String password) {
        long matchCount = userDao.countByUserNameAndPassword(userName, password);
        return matchCount > 0;
    }
}

public interface UserRegistry extends JpaRepository<User, Integer> {
    long countByUserNameAndPassword(String userName, String password);
}

我们的测试代码可能会这么写:

when(userService.hasMatchUser("admin", "123456")).thenReturn(true);

但是如果这么写,会报错:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: 
Boolean cannot be returned by countByUserNameAndPassword()
countByUserNameAndPassword() should return long

“正确”写法应该是这样:

doReturn(true).when(userService).hasMatchUser("admin", "123456");

但是这样仍然会报错:

org.mockito.exceptions.misusing.NotAMockException: 
Argument passed to when() is not a mock!

因为service本身不是一个mock过的对象,所以应该把它“变”成一个mockito的对象,但是我们想调用的是真实的service,所以应该用spy而不是mock:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest extends AbstractJUnit4SpringContextTests {
    @Mock
    private UserRegistry userDao;

    @Spy
    @InjectMocks
    private UserService userService;
}

这样就能开展正常的测试了。

参考资料

  1. when I run mockito test occurs WrongTypeOfReturnValue Exception
  2. WrongTypeOfReturnValue when nesting when().thenReturn
  3. I get NotAMockException when trying to partially mock a void method - what am I doing wrong?
发布了110 篇原创文章 · 获赞 132 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/HermitSun/article/details/104978004