Java 模拟接口存储库

Java 模拟接口存储库,java,unit-testing,junit,mocking,mockito,Java,Unit Testing,Junit,Mocking,Mockito,我应该模仿其他人编写的存储库 我有一个界面IUserDetailsRepository,它只查询数据库以手动(而不是通过create user方法)检索存储在其中的用户详细信息(finduser())。方法finduser()在helper类中实现,并由服务类使用。此类具有getuser()方法,其中调用了finduser()。我怎么嘲笑这个?我应该模拟服务类并调用getuser()还是必须模拟helper类并调用finduser()存储库方法 我被这件事缠住了。。由于我没有createuser

我应该模仿其他人编写的存储库

我有一个界面
IUserDetailsRepository
,它只查询数据库以手动(而不是通过create user方法)检索存储在其中的用户详细信息(
finduser()
)。方法
finduser()
在helper类中实现,并由服务类使用。此类具有getuser()方法,其中调用了
finduser()
。我怎么嘲笑这个?我应该模拟服务类并调用
getuser()
还是必须模拟helper类并调用
finduser()
存储库方法

我被这件事缠住了。。由于我没有createuser,我如何模拟对象并注入。我完全糊涂了。请帮帮我

如果有任何这样的编程结构被解释为如何模拟,那将是非常有帮助的

这是密码

 **********IUserDetails Repository************

@Repository
public interface IUserDetails 
    extends PagingAndSortingRepository<UserEntity,String>
{
    @Query("select ud.id,ud.name,ud.unit from UserEntity u where ud.id=:id and ud.passwd=:passwd")
    List<Object[]> findUserbyID(@Param("id") String id, @Param("passwd") String passwd);
}


*****UserHelper class*****
@Component
public class UserHelper{
@Autowired 
private IUserDetails repo;
@Transactional(rollbackFor=(Exception.class);
@ExceptionHandler(Exception.class)
publib List<UserDetailsDTO> findUserbyID(String id, String passwd)
{
List<UserDetailsDTO> user=new ArrayList<UserDetailsDTO>();
List<Object[]> repouser=repo.findUserbyID(id,passwd);
UserDetailsDTO udto=new UserDetailsDTO();
for(Object[] ob:repouser)
{
udto.setid((String)ob[0]));
udto.setname((String)ob[1]));
udto.setunit((String)ob[2]));
user.add(udto);
}
return user;
}

*********UserDetailsDTO ********
public class UserDetailsDTO implements Serializable{
private String id,name,unit,passwd;
    public String setid(String id)
    {this.id=id;}
    public String setpasswd(String passwd)
    {this.passwd=passwd;}
    public String setname(String name)
    {this.name=name;}
    public String setunit(String unit)
    {this.unit=unit;}
    public String getid()
    {return id;}
    public String getname()
    {return name;}
    public String getunit()
    {return unit;}
    public String getpasswd()
    {return passwd;}
}


*********UserDetailsService********
public class UserDetailsService{
    @Autowired 
    private UserHelper helper;
    public List<UserDetailsDTO> getUser(@PathVariable("id") String id, @PathVariable("passwd") String passwd)
    {
        List<UserDetailsDTO> udto=new ArrayList<UserDetailsDTO>();
        udto=helper.findUserbyID(id,passwd);
        if(udto==null)
        throw new UserNotFound(id);
    return udto;
    }
}


************Test class**********
Importing junit and mockito related packages;
@RunWith(MockitoJUnitRunner.class)
public class UserDetailsTest{

@InjectMocks
UserDetailsService service;

@Mock
IUserDetails rep;

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

@Test
public void TestFindUser()
{
    UserDetailsDTO details=new UserDetailsDTO();
    detail.setid("123");
    details.setpasswd("p@wd");
    details.sename("MyName");
    details.setunit("Engg");

    Mockito.when(rep.findUserbyId("123","p@wd")).thenReturn(details);  
    // Throws me error related to mismatch return types
    //when i change it to thenReturn((List<Object[]>)details), it throws error that it is not able to stub

    List<UserDetailsDTO> ud=serrvice.getUser("123","p@wd");
    asserThat(ud,is(notNullValue()));
    assertEquals(ud,details);
}
}
*******IUserDetails存储库************
@存储库
公共界面详细信息
扩展分页和排序存储库
{
@查询(“从UserEntity u中选择ud.id、ud.name、ud.unit,其中ud.id=:id和ud.passwd=:passwd”)
列出findUserbyID(@Param(“id”)字符串id、@Param(“passwd”)字符串passwd);
}
*****UserHelper类*****
@组成部分
公共类用户助手{
@自动连线
私人回购;
@事务(rollboor=(Exception.class);
@ExceptionHandler(Exception.class)
publib列表findUserbyID(字符串id、字符串密码)
{
List user=new ArrayList();
List repouser=repo.finduserbyd(id,passwd);
UserDetailsDTO udto=新的UserDetailsDTO();
对于(对象[]对象:用户)
{
udto.setid((字符串)ob[0]);
setname((字符串)ob[1]);
setunit((字符串)ob[2]);
user.add(udto);
}
返回用户;
}
*********用户详细信息********
公共类UserDetailsTo实现可序列化{
私有字符串id、名称、单位、密码;
公共字符串集合id(字符串id)
{this.id=id;}
公共字符串setpasswd(字符串passwd)
{this.passwd=passwd;}
公共字符串集合名(字符串名)
{this.name=name;}
公共字符串设置单元(字符串单元)
{this.unit=unit;}
公共字符串getid()
{返回id;}
公共字符串getname()
{返回名称;}
公共字符串getunit()
{返回单元;}
公共字符串getpasswd()
{return passwd;}
}
*********用户详细信息服务********
公共类UserDetailsService{
@自动连线
私人用户助手;
公共列表getUser(@PathVariable(“id”)字符串id,@PathVariable(“passwd”)字符串passwd)
{
List udto=new ArrayList();
udto=helper.findUserbyID(id,passwd);
if(udto==null)
抛出新的UserNotFound(id);
返回udto;
}
}
************测试班**********
导入junit和mockito相关包;
@RunWith(MockitoJUnitRunner.class)
公共类UserDetailsTest{
@注射模拟
用户详细信息服务;
@嘲弄
IUSERREP;
@以前
公共作废设置()
{
initMocks(this);
}
@试验
公共void TestFindUser()
{
UserDetailsDTO details=新的UserDetailsDTO();
详细信息。setid(“123”);
详细信息。setpasswd(“p@wd");
详细信息。sename(“我的名字”);
详细信息。设置单位(“工程”);
Mockito.when(代表Finduserbyd(“123”)p@wd)然后返回(详细信息);
//抛出与不匹配的返回类型相关的错误
//当我将其更改为thenReturn((List)details)时,它会抛出一个错误,即它无法存根
List ud=serservice.getUser(“123”p@wd");
资产(ud,is)(notNullValue());
资产质量(ud,详细信息);
}
}

UserDetailsService
的角度来看,您不需要模拟
IUserDetails
,而是
UserHelper

public class UserDetailsTest{

@InjectMocks
UserDetailsService service;

@Mock
UserHelper helperMock;

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

@Test
public void TestFindUser()
{
    UserDetailsDTO details=new UserDetailsDTO();
    detail.setid("123");
    details.setpasswd("p@wd");
    details.sename("MyName");
    details.setunit("Engg");

    List<UserDetailsDTO> userList = new ArrayList<>();
    userList.add(details);

    Mockito.when(helperMock.findUserbyID("123","p@wd")).thenReturn(userList);  

    List<UserDetailsDTO> resultUserList=serrvice.getUser("123","p@wd");
    asserThat(ud,is(notNullValue()));
    assertThat("Size", userList.size(), equalTo(resultUserList.size());
    assertEquals("Details",details, equalTo(resultUserList.get(0)));
}

可能添加一些带有实际方法签名的代码会简化其他人对您的问题的理解Hi@SergGr,我编辑了我的帖子并添加了代码。还添加了我的测试代码。谢谢。这是一个很大的帮助。我将尝试解决这个问题。如果您能进一步解释一下为什么在两个不同的类中编写了类和接口模拟这将对我有所帮助。你可以模拟接口或类。我已经拆分了测试,因为你不应该调用直接依赖的代码。这就是为什么我从服务测试中模拟UserHelper。我不关心UserHelper(使用Repo接口)的内部内容…Repo只对UserHelper类才重要。希望helpsHint:当您已经在使用mockito运行程序时,没有必要将@Before与
MockitoAnnotations.initMocks(this)
一起使用。无论是runner还是initMocks();两者都做相同的事情!我在返回时再次遇到与以前相同的错误(详细信息)由于类型OnGoingStubing中的thenReturn(List)方法不适用于参数(UserDetailsTo)。事实上,我尝试将该类型强制转换为List,这给了我一个新错误。“在此处检测到未完成的存根:”好的,我得到了它..我将userList传递给了theReturn(),而不是details,它成功了
    public class UserHelperTest{

    @InjectMocks
    UserHelper userHelper;

    @Mock
    IUSerDetails repo;

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

    @Test
    public void shouldFindUserById()
    {
        String id = "id";
        String name = "name";
        String unit = "unit";
        String passwd = ""passwd";

        List<Object[]> queryResult = new ArrayList<>(); 
        queryResult.add(new Object[]{id,name,unit});

        Mockito.when(repo.findUserByID(id,passwd)).thenReturn(queryResult));

        List<UserDetailsDTO> resultList = userHelper.findUserbyID(id,passwd);

        // assertions on size and content of first element..