简体   繁体   English

无法在Jmockit中模拟具有通用返回类型的接口

[英]Unable to mock interface with generic return type in Jmockit

I am trying to write a Junit unit test which mocks an interface that extends the spring-data-jpa interface CrudRepository<T, ID extends Serializable>. 我正在尝试编写一个Junit单元测试,该单元测试模拟了一个接口,该接口扩展了spring-data-jpa接口CrudRepository <T,ID扩展了Serializable>。 This interface provides the method 该接口提供了方法

<S extends T> S save(S entity);

When I call this in my Expectations it wrongly records the return type as the type of the mocked interface rather than S (as resolved by my mocked interface) which causes a class cast exception. 当我在我的Expectations中调用此函数时,它错误地将返回类型记录为模拟接口的类型,而不是S(由我的模拟接口解析)作为类型的转换异常。

I have debugged through and the generic signature it records is 我已经调试通过,它记录的通用签名是

<S:TT;>(TS;)TT;

There is a lot of code around figuring out what the return type is but eventually it comes up with the wrong answer. 有很多代码可以弄清楚返回类型是什么,但最终会给出错误的答案。 I'm fairly sure this is a bug but I hope someone can confirm this or tell me where I'm going wrong. 我相当确定这是一个错误,但我希望有人可以确认这一点或告诉我我要去哪里。 One other thing to note is I am able to successfully mock other calls on the interface that just return T. 要注意的另一件事是,我能够在仅返回T的接口上成功模拟其他调用。

  • Jmockit: 1.16 Jmockit:1.16
  • JUnit: 4.12 JUnit的:4.12
  • spring-data-jpa: 1.7.1.RELEASE spring-data-jpa:1.7.1。发布

Update with example 用示例更新

I have put together a scaled down test case that demonstrates the issue (below). 我整理了一个按比例缩小的测试用例,用以说明问题(如下)。 In doing so I have uncovered a strange quirk. 通过这样做,我发现了一个奇怪的怪癖。 In the test I have two MyEntity objects which I use in the two expectations. 在测试中,我有两个MyEntity对象,可以在两个期望中使用它们。 If I change the save expectation to take and return the same objecct as the findOne call, the bug does not occur. 如果更改保存期望并返回与findOne调用相同的objecct,则不会发生该错误。

MyEntity.java MyEntity.java

import javax.persistence.Entity;

@Entity
public class MyEntity
{
}

MyRepository.java MyRepository.java

import org.springframework.data.repository.CrudRepository;

public interface MyRepository extends CrudRepository<MyEntity, Long>
{

}

DataAccess.java DataAccess.java

public class DataAccess
{
    private final MyRepository repository;

    public DataAccess(MyRepository repository)
    {
        this.repository = repository;
    }

    public MyEntity resaveEntity(long id)
    {
        MyEntity entity = repository.findOne(id);
        return repository.save(entity);
    }
}

DataAccessTest.java DataAccessTest.java

import mockit.Expectations;
import mockit.Mocked;
import org.junit.Test;

public class DataAccessTest
{

    @Test
    public void testResaveEntity(@Mocked final MyRepository repository) throws Exception
    {
        final MyEntity myEntity = new MyEntity();
        final MyEntity myEntity2 = new MyEntity();
        new Expectations()
        {
            {
                repository.findOne(1L);
                result = myEntity;

                repository.save(myEntity2);
                result = myEntity2;
            }
        };

        DataAccess dataAccess = new DataAccess(repository);
        dataAccess.resaveEntity(1);
    }
}

Exception 例外

java.lang.ClassCastException: $Impl_MyRepository cannot be cast to MyEntity
at DataAccess.resaveEntity(DataAccess.java:16)
at DataAccessTest.testResaveEntity(DataAccessTest.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

There is an error in the test. 测试中有错误。 Where it reads 它读的地方

repository.save(myEntity2);

it should be 它应该是

repository.save(myEntity1);

With this fix, the test should pass. 有了此修复程序,测试应该可以通过。 On the other hand, that ClassCastException occurs because of a bug in JMockit, for which an issue was opened. 在另一方面, ClassCastException发生,因为在JMockit中的错误,对其中的问题被打开了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM