我无法将Mockito单位测试重写为SPOCK规范



我有Spring接口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是标准接口ExtendNG JpaRepository<UserEntity, Long>,其中UserEntity是我的模型类。

User是从弹簧框架中的UserDetails实现。

和我使用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:

您需要在一个步骤中进行固执和验证

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

有关详细信息,这是我从Spock中的预定义模拟响应中的答案:

请参阅文档

嘲笑和固定相同的方法调用时,它们必须在相同的互动中发生。特别是,以下模仿风格的固执和模拟分为两个单独的陈述将无效:

setup:
subscriber.receive("message1") >> "ok"
when:
publisher.send("message1")
then:
1 * subscriber.receive("message1")

正如在何处声明互动中所述,接收呼叫将首先与当时的块中的交互作用相匹配。由于该交互没有指定响应,因此将返回该方法返回类型的默认值(在这种情况下为NULL)。(这只是Spock宽大嘲笑方法的另一个方面。)。因此,设置:块中的交互永远不会有机会匹配。


在处理春季和交易代理时,您可能还会遇到此问题https://github.com/spockframework/spock/spock/issues/758

相关内容

  • 没有找到相关文章

最新更新