gpt4 book ai didi

java - 使用 Spring Security 的 Principal 的单元测试方法

转载 作者:行者123 更新时间:2023-11-29 04:34:42 25 4
gpt4 key购买 nike

谁能告诉我应该如何测试这两种方法:

public boolean deleteUser(Principal principal) {
if (findLoggedInUser(principal) != null) {
userRepository.delete(findLoggedInUser(principal));
return true;
}
return false;
}

public User findLoggedInUser(Principal principal) {
return findUserbyUsername(principal.getName());
}

问题是我正在使用具有基本身份验证的当前登录用户,但不知道如何操作,也不知道我是否可以模拟这些委托(delegate)人。有没有办法做到这一点?这些方法在我的服务层中,所以我可能无法进行单元测试,只能进行集成测试,因为这些方法大量使用数据库?

编辑 1:我更改的测试类:

public class UserServiceBeanTest {

@Spy
@InjectMocks
private UserServiceBean userServiceBean;

@Mock
private UserRepository userRepository;

@Mock
private Principal principal;

@Mock
private PasswordEncoder passwordEncoder;

@Mock
private User userStub;

private String defaultName = "user";
private String defaultPassword = "password";
private String defaultEmail = "example@example.com";

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


@Test
public void shouldReturnTrue_whenUserDeleted() {
//given
when(principal.getName()).thenReturn(defaultName);
when(userServiceBean.findLoggedInUser(principal)).thenReturn(userStub);

// when
boolean removed = userServiceBean.deleteUser(principal);

//then
assertTrue(removed);
verify(userRepository, times(1));
}

@Test
public void shouldReturnFalse_whenUserNotFound() {
//given
when(principal.getName()).thenReturn(defaultName);
when(userServiceBean.findLoggedInUser(principal)).thenReturn(null);

//when
boolean removed = userServiceBean.deleteUser(principal);

//then
assertFalse(removed);
verify(userRepository, times(0));
}

}

我现在遇到这些错误:

org.mockito.exceptions.misusing.UnfinishedVerificationException: 

小姐

g method call for verify(mock) here:
-> at com.doublemc.services.UserServiceBeanTest.shouldReturnTrue_whenUserDeleted(UserServiceBeanTest.java:63)

Example of correct verification:
verify(mock).doSomething()

Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.


at com.doublemc.services.UserServiceBeanTest.init(UserServiceBeanTest.java:48)

编辑 2:这是我的 UserServiceBean 类:

package com.doublemc.services;

import com.doublemc.domain.ToDoItem;
import com.doublemc.domain.User;
import com.doublemc.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.security.Principal;

@Service
@Transactional
public class UserServiceBean {

private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;

@Autowired
UserServiceBean(UserRepository userRepository, PasswordEncoder passwordEncoder) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}

public User saveUser(User user) {
User newUser = new User();
newUser.setUsername(user.getUsername());
newUser.setEmail(user.getEmail());
newUser.setPassword(passwordEncoder.encode(user.getPassword()));
return userRepository.save(newUser);
}

public boolean userExists(User user) {
return userRepository.findByUsername(user.getUsername()) != null;
}

public Iterable<ToDoItem> getAllToDoItems(User user) {
return user.getToDoItems();
}

public boolean deleteUser(Principal principal) {
if (findLoggedInUser(principal) != null) {
userRepository.delete(findLoggedInUser(principal));
return true;
}
return false;
}

public User findLoggedInUser(Principal principal) {
return userRepository.findByUsername(principal.getName());
}

这是我的 UserRepository:

public interface UserRepository extends CrudRepository<User, Long> {
User findByUsername(String username);
}

编辑 6:我为自己创建了另外三个测试:

@Test
public void shouldReturnUser_whenPassedUser() {
// given
when(userRepository.save(any(User.class))).thenReturn(new User(defaultName, defaultPassword, defaultEmail));

// when
User savedUser = userServiceBean.saveUser(userStub);

// then
assertNotNull(savedUser);
verify(userRepository, times(1)).save(any(User.class));
}

@Test
public void shouldReturnTrue_whenUserExists() {
// given
when(userStub.getUsername()).thenReturn(defaultName);
when(userRepository.findByUsername(userStub.getUsername())).thenReturn(userStub);

// when
boolean exists = userServiceBean.userExists(userStub);

// then
assertTrue(exists);
verify(userRepository, times(1)).findByUsername(defaultName);
}

@Test
public void shouldReturnFalse_whenUserNotFoundByUsername() {
// given
when(userStub.getUsername()).thenReturn(defaultName);
when(userRepository.findByUsername(userStub.getUsername())).thenReturn(null);

// when
boolean exists = userServiceBean.userExists(userStub);

// then
assertFalse(exists);
verify(userRepository, times(1)).findByUsername(defaultName);
}

下面是经过测试的方法:UserServiceBean.saveUser:

public User saveUser(User user) {
User newUser = new User(user.getUsername(), user.getEmail(), passwordEncoder.encode(user.getPassword()));
return userRepository.save(newUser);
}

UserServiceBean.userExists:

public boolean userExists(User user) {
return userRepository.findByUsername(user.getUsername()) != null;
}

最佳答案

这就是我的做法(Junit + Mockito)。

在给定的例子中有两个测试用例。

顺便说一句..我想你可以做一点重构,因为你(我猜)两次访问数据库:

public boolean deleteUser(Principal principal) {
User loggedUser = findLoggedInUser(principal);
if (loggedUser != null) {
userRepository.delete(loggedUser);
return true;
}
return false;
}

为了测试..

import static org.mockito.Mockito.*;
import mypkg.Service;
import mypkg.User;
import mypkg.UserRepository;
import org.junit.Assert;
import org.junit.Before;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;

import java.security.Principal;

public class ServiceTest {

@Spy
@InjectMocks
private Service service;

@Mock
private UserRepository userRepository;

@Mock
private Principal principal;

@Mock
private User userStub;

private String defaultName = "name";

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

@org.junit.Test
public void shouldReturnTrue_whenUserDeleted() throws Exception{
// Arrange
when(principal.getName()).thenReturn(defaultName);
when(service.findUserbyUsername(defaultName)).thenReturn(userStub);

// Act
boolean removed = service.deleteUser(principal);

// Assert
Assert.assertTrue(removed);
verify(userRepository, times(1)).delete(userStub);
}

@org.junit.Test
public void shouldReturnFalse_whenUserNotFound() throws Exception{
// Arrange
when(principal.getName()).thenReturn(defaultName);
when(service.findUserbyUsername(defaultName)).thenReturn(null);

// Act
boolean removed = service.deleteUser(principal);

// Assert
Assert.assertFalse(removed);
verify(userRepository, times(0)).delete(userStub);
}
}

最重要的事情是模拟/ stub 任何外部依赖项(在本例中为 UserRepository)并仅关注该服务方法中包含的逻辑。 delete 内部的内容与测试无关。您关心的只是该方法是否已使用特定参数调用。仅此而已。

如果一切都清楚,请告诉我。如果需要,我会解释。

更新

@InjectMocks 是一种将依赖项注入(inject)您要测试的类的便捷方法。注入(inject)通过 setter /构造函数发生,或者作为最后的手段通过反射发生。

在上面的示例中,Service 类具有 UserRepository 依赖项,并且定义了一个 @Mock:

@Mock
private UserRepository userRepository;

Mockito 会将其注入(inject)到 Service 中。

@Spy 类似于 @Mock,不同之处在于它允许您有选择地仅模拟某些行为,并且默认情况下会调用真正的实现。

在我的例子中,我用它来模拟 ServicefindUserbyUsername 方法,因为里面发生的事情在我们的两个测试中并不重要:

when(service.findUserbyUsername(defaultName)).thenReturn(userStub);

关于java - 使用 Spring Security 的 Principal 的单元测试方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42148257/

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