[英]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的接口上成功模拟其他调用。
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.