Java 任何模拟框架都允许监视超级类方法吗?

Java 任何模拟框架都允许监视超级类方法吗?,java,unit-testing,mocking,mockito,superclass,Java,Unit Testing,Mocking,Mockito,Superclass,我们正在使用SpringOAuth,有几个地方需要使用继承 在当前情况下,我们正在扩展令牌端点 public class MyTokenEndpoint extends TokenEndpoint { //... public ResponseEntity<OAuth2AccessToken> getAccessToken( Principal principal, MyParams myParams,

我们正在使用SpringOAuth,有几个地方需要使用继承

在当前情况下,我们正在扩展令牌端点

public class MyTokenEndpoint extends TokenEndpoint {
    //...
    public ResponseEntity<OAuth2AccessToken> getAccessToken(
            Principal principal,
            MyParams myParams,
            @RequestParam Map<String, String> allParams) {

        // .. Stuff Happens

        updateParamsWithStuff(allParams);

        return super.getAccessToken(
        principal, myParams.grantType(), allParams);
    }
    //...
}
公共类MyTokenEndpoint扩展了TokenEndpoint{
//...
公共响应性getAccessToken(
校长,
MyParams MyParams,
@RequestParam映射所有参数){
//…事情发生了
updateParamsWithStuff(所有参数);
返回super.getAccessToken(
主体,myParams.grantType(),allParams);
}
//...
}
现在我要测试的是,传递给super.getAccessToken的映射是否已填充了内容。我的简单方法是监视传入的映射,但这依赖于implementation详细信息,实际上并不确保在传入的映射super.getAccessToken中有内容

我们使用的是Mockito,我看到一些评论认为这是行不通的,也有一些评论暗示这可能是行不通的。这可以在任何模拟框架中实现吗

查看(,勾选的一个表示不可能,但考虑到第二个答案的讨论,我不得不尝试。)

在阅读之后,我尝试了以下方法:

MyTokenEndpoint spyEndpoint = Mockito.spy(endpoint); //endpoint Set-up previously

Mockito.doAnswer(new Answer<ResponseEntity<OAuth2AccessToken>>() {
    @Override
    public ResponseEntity<OAuth2AccessToken> 
           answer(InvocationOnMock invocation) {
       Object[] args = invocation.getArguments();
       Map<String, String> params = (Map<String, String>) args[2];
       System.out.printf("%s\n", params.toString());
       return new ResponseEntity<OAuth2AccessToken>(HttpStatus.ACCEPTED);
    }
}).when(((TokenEndpoint) spyEndpoint))
.getAccessToken(any(Principal.class), 
                anyString(), (Map<String, String>) anyMap());

theResponse = spyEndpoint
                .getAccessToken(principal, 
                                myPrams,
                                currentMap);
MyTokenEndpoint spyEndpoint=Mockito.spy(端点)//以前设置的终结点
Mockito.doAnswer(新答案(){
@凌驾
公共责任
应答(调用锁调用){
对象[]args=invocation.getArguments();
Map params=(Map)args[2];
System.out.printf(“%s\n”,params.toString());
返回新的响应状态(HttpStatus.ACCEPTED);
}
}).何时(((令牌端点)spyEndpoint))
.getAccessToken(任何(主体类),
anyString(),(Map)anyMap();
响应=SPYEND点
.getAccessToken(委托人,
迈普拉斯,
当前地图);
但答案中的代码永远不会被调用


我找错树了吗??这在任何模拟框架中都可能吗?

为什么需要模拟?您已经在扩展该类--只需重写该方法,检查传入的数据,然后将数据转发给父级即可。

这样的测试可以很容易地用以下方法编写:

@测试
public void mockCallToSuper(@Mocked final tokenpoint mockedBase)
{
final Principal=null;//或其他
MyParams MyParams=新的MyParams();
Map params=新的HashMap();
响应性访问令牌=
新建MyTokenEndpoint().getAccessToken(主体、myParams、params);
//“accessToken”上的断言
新的核查(){{
地图;
mockedBase.getAccessToken(
principal,(MyParams)any,actualParams=withCapture());
资产质量(“abc”,actualParams.get(“A”);
assertEquals(“另一项”,actualParams.get(“B2”);
}};
}

据我所知,没有办法模仿超级方法。这将打破java使用的多态机制。我使用过的最强大的模拟库Powermock(据我所知)无法模拟“super.xxx()”mathodsThanks Adam。我担心这就是答案。好吧,我的模拟符还在发展中。。但是调用已经有一个具有相同签名的重写方法,如果调用该方法,将抛出异常。这就是我们调用super.oldMethod的原因。我还需要强制返回值。我正在发送一个模拟对象以强制执行异常。如果我不能捕获对super的调用,我最终需要一个返回模拟对象的模拟对象,测试很快就会变得混乱和脆弱。没问题。要为调用
super.getAccessToken(…)
提供一个返回值,您需要使用分配给
result
字段的所需返回值记录对它的期望值。
@Test
public void mockCallToSuper(@Mocked final TokenEndpoint mockedBase)
{
   final Principal principal = null; // or whatever
   MyParams myParams = new MyParams();
   Map<String, String> params = new HashMap<String, String>();

   ResponseEntity<OAuth2AccessToken> accessToken =
      new MyTokenEndpoint().getAccessToken(principal, myParams, params);

   // asserts on "accessToken"

   new Verifications() {{
      Map<String, String> actualParams;
      mockedBase.getAccessToken(
         principal, (MyParams) any, actualParams = withCapture());

      assertEquals("abc", actualParams.get("A"));
      assertEquals("another item", actualParams.get("B2"));
   }};
}