gpt4 book ai didi

java - 我无法将 Mockito 单元测试重写为 Spock 规范

转载 作者:行者123 更新时间:2023-12-02 12:17:50 24 4
gpt4 key购买 nike

我有一个 Spring 接口(interface)的实现 UserDetailsService :

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

private final UserRepository userRepository;

@Autowired
public UserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
final UserEntity user = userRepository.findByUsername(username);

if (user == null) {
throw new UsernameNotFoundException("Cannot find user with username " + username);
}

return new User(user);
}
}

UserRepository是一个标准接口(interface)扩展JpaRepository<UserEntity, Long>哪里UserEntity是我的模型类。

UserUserDetails 的实现来自 Spring 框架。

我使用 JUnit 和 Mockito 为这个方法编写了一个单元测试。这些测试有效:

@RunWith(SpringRunner.class)
@DirtiesContext
public class UserDetailsServiceTest {

@Autowired
private UserDetailsService userDetailsService;

@Test
public void shouldFindUser() throws Exception {
// given
final UserEntity user = new UserEntity(
1L,
"username",
"username@email.com",
"password",
new ArrayList<>() // list of roles
);

when(UserDetailsServiceTestContext.userRepository.findByUsername(user.getUsername()))
.thenReturn(user);

// when
final UserDetails result = userDetailsService.loadUserByUsername(user.getUsername());

// then
assertThat(result).isEqualTo(UserFactory.create(user));
verify(UserDetailsServiceTestContext.userRepository)
.findByUsername(user.getUsername());
}

@Test(expected = UsernameNotFoundException.class)
public void shouldNotFindUser() throws Exception {
// given
when(UserDetailsServiceTestContext.userRepository.findByUsername(anyString()))
.thenReturn(null);

// when
final UserDetails result = userDetailsService.loadUserByUsername(new String());
}

@TestConfiguration
static class UserDetailsServiceTestContext {

@MockBean
private static UserRepository userRepository;

@Bean
UserDetailsService userDetailsService() {
return new UserDetailsServiceImpl(userRepository);
}
}

}

现在我尝试使用 Groovy 和 Spock 框架编写这些测试。我写了以下规范:

def 'should find user'() {
given:
def user = new UserEntity(
1L,
"username",
"username@email.com",
"password"
new ArrayList<>() // list of roles
)

userRepository.findByUsername(user.username) >> user
// userRepository.findByUsername(_ as String) >> user // also working

when:
def result = userDetailsService.loadUserByUsername(user.username)

then:
result == new User(user)
}

并且此测试正在运行。但是当我想通过在 then: 节中添加来验证 userRepository 的调用时声明1 * userRepository.findByUsername(user.username)1 * userRepository.findByUsername(_ as String)我收到错误 UserDetailsServiceSpec.should find user and return new User:36 » UsernameNotFound 。第 36 行位于 when: 部分

最佳答案

您需要一步完成 stub 和验证

then:
1 * userRepository.findByUsername(user.username) >> user

详细信息是我在 Predefined mock response in Spock 的回答:

请引用documentation

When mocking and stubbing the same method call, they have to happen in the same interaction. In particular, the following Mockito-style splitting of stubbing and mocking into two separate statements will not work:

setup:
subscriber.receive("message1") >> "ok"

when:
publisher.send("message1")

then:
1 * subscriber.receive("message1")

As explained in Where to Declare Interactions, the receive call will first get matched against the interaction in the then: block. Since that interaction doesn’t specify a response, the default value for the method’s return type (null in this case) will be returned. (This is just another facet of Spock’s lenient approach to mocking.). Hence, the interaction in the setup: block will never get a chance to match.

<小时/>

在处理 spring 和事务代理时,您也可能会遇到这个问题 https://github.com/spockframework/spock/issues/758

关于java - 我无法将 Mockito 单元测试重写为 Spock 规范,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46024769/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com