EasyMock-调用具有不同签名的方法时,行为已更改

时间:2019-08-23 18:18:10

标签: java easymock java-11

我目前有一个使用EasyMock 3.4可以正常运行的单元测试,但是当我尝试使用EasyMock 4.0.2进行编译和运行时,我注意到了一个我不太了解的奇怪行为:

我有一个具有以下两种方法的类(请注意签名更改):

public TestAccessSource setAccess(Class<?> clazz, Object access) {
    return setAccess(clazz.getName(), access);
}

public TestAccessSource setAccess(Class<?> clazz, InterfaceA access) {
    return setAccess(clazz, (Object) access);
}

我在单元测试中调用了setAccess方法,如下所示:

testSources.setAccess(InterfaceB.class, EasyMock.createNiceMock(InterfaceB.class));

在3.4中,调用以setAccess作为第二个参数的Object方法,在4.0.2中,调用以setAccess作为第二个参数的InterfaceA方法,抛出java.lang.ClassCastException,因为接口不相关-它们唯一的共同之处在于它们扩展了Remote接口。

如果我只是使用InterfaceB的实现而不是模拟它,则会调用正确的setAccess方法:

testSources.setAccess(InterfaceB.class, new InterfaceB(){});

这里是重现此行为的完整示例。第一个setAccess有效,但是第二个失败。在EasyMock 3.4上运行时,两者都可以正常工作:

public class TestEasyMockBehavior {

    public static void main(String[] args) {
        TestAccessSource testSources = new TestAccessSource();
        testSources.setAccess(InterfaceB.class, new InterfaceB(){});
        testSources.setAccess(InterfaceB.class, EasyMock.createNiceMock(InterfaceB.class));
    }

    public static class TestAccessSource {
        public TestAccessSource setAccess(Class<?> clazz, Object access) {
            return setAccess(clazz.getName(), access);
        }

        public TestAccessSource setAccess(Class<?> clazz, InterfaceA access) {
            return setAccess(clazz, (Object) access);
        }

        public TestAccessSource setAccess(String key, Object access) {
            System.out.println(key + " - " + access.getClass().getName());
            return this;
        }
    }

    public interface InterfaceA extends Remote {}

    public interface InterfaceB extends Remote {}
}

我正在寻找帮助,以了解发生的原因以及发生了什么变化。我找不到与此行为有关的任何问题。

1 个答案:

答案 0 :(得分:4)

它与EasyMock 4而不是Java 11有关。实际上,我更改了EasyMock 4的类型。在<table> <tbody> <tr ng-if="PlacesOfInterest.length > 0" role="row" class="text-center" ng-repeat="row in PlacesOfInterest | filter: search | limitTo: limit as filterPlaces " ng-cloak> <td style="vertical-align:middle"><span class="" ng-bind="row.PlaceName"></span></td> {{row.PlaceName}} <td><img ng-if="row.PlacePhotos.length > 0" src="{{row.PlacePhotos[0].URL}}" alt="No Image" style="height:150px; width:100%" /></td> <td> <span ng-init="max = 200" ng-bind="row.PlaceDescription.slice(0,max)"></span> <a ng-show="row.PlaceDescription.length > 200 && max == 200" ng-click="max = 10000">... <span class="more-less"> more</span></a> <a class="more-less" ng-show="max > 200" ng-click="max = 200"> less</a> </td> <td> <div class="d-flex"> <a class="btn btn-sm mr-1 btn-modify-places btn-min-width">Edit</a> <a class="btn btn-sm mr-1 btn-default-places btn-min-width">Specialities</a> <a class="btn btn-sm btn-delete-places btn-min-width">Delete</a> </div> </td> </tr> </tbody> </table>之前。真令人讨厌,因为一旦您想T mock(Class<T>)就会收到警告。

因此,我决定键入List<String> list = (List) mock(List.class)。问题解决了,类型被推断。

缺点是在某些情况下无法推断出,或者更罕见的是无法正确推断出。但是这些情况在我看来是例外的,因为一般来说,您将模拟分配给变量以能够记录内容然后重播。

要解决您的问题,您有两种解决方法:

  1. T mock(Class<?>)
  2. testSources.setAccess(InterfaceB.class, (InterfaceB) mock(InterfaceB.class));