简体   繁体   English

Mockito spy() 导致 java.lang.ExceptionInInitializerError

[英]Mockito spy() causes java.lang.ExceptionInInitializerError

I am trying to use initialize a regular Mockito spy like this我正在尝试使用像这样初始化常规 Mockito 间谍

StorageItem storageItemMock = Mockito.spy(cargoAdministration
                                     .addCargo(CargoType.MIXED, 
                                               new CustomerImp("Human"),
                                               BigDecimal.ONE, 
                                               hazards, true, false));

cargoAdministration.inspect(storageItemMock.getPosition());

verify(storageItemMock, times(1)).getCargo().inspect();

The addCargo method returns a StorageItem so that should not be the problem. addCargo方法返回一个StorageItem所以这不应该是问题。 I want to verify a method from the StorageItem spy.我想verify StorageItem间谍的方法。

Every time I try to run this test I get following exception:每次我尝试运行此测试时,都会出现以下异常:

java.lang.ExceptionInInitializerError

Caused by: java.lang.IllegalStateException: Failed to load interface org.mockito.plugins.MockMaker implementation declared in java.lang.CompoundEnumeration@3d34d211

Caused by: java.lang.IllegalStateException: Error during attachment using: ByteBuddyAgent.AttachmentProvider.Compound{attachmentProviders=[ByteBuddyAgent.AttachmentProvider.ForJigsawVm.INSTANCE, ByteBuddyAgent.AttachmentProvider.ForJ9Vm.INSTANCE, ByteBuddyAgent.AttachmentProvider.ForToolsJarVm.JVM_ROOT, ByteBuddyAgent.AttachmentProvider.ForToolsJarVm.JDK_ROOT, ByteBuddyAgent.AttachmentProvider.ForToolsJarVm.MACINTOSH]}

Caused by: java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)

Caused by: java.io.IOException: Can not attach to current VM

You can use ArgumentCaptor instead of Spy in your case in order to catch the element passed to your method;您可以在您的案例中使用 ArgumentCaptor 而不是 Spy 来捕获传递给您的方法的元素;

@Mock
StorageItem storageItemMock;

@Captor
ArgumentCaptor<Hazard> hazardCaptor;

@Test
public void yourTest(){
  // assertion
  verify(storageItemMock, times(2)). addCargo(hazardCaptor.capture());

  // mail is sent after notification
  Hazard mailEvent = (Haeard) hazardCaptor.getAllValues().get(1);
  assertThat(hazard.getter(), equalTo(the passed object));
}

I don't know if this is what causes the error, but我不知道这是否是导致错误的原因,但是

verify(storageItemMock, times(1)).getCargo().inspect();

will not work, even if storageItemMock is a spy - the verify can check that getCargo() is called on the spy, but not the inspect() call because that's called on a real object (and out of range of the verify() ).将不起作用,即使storageItemMock是间谍 - verify可以检查getCargo()是否在间谍上被调用,但不是inspect()调用,因为它是在真正的 object 上调用的(并且超出了verify()的范围) .

As for the cargo/position/map issue, I feel the addPosition -method does too much;至于货物/位置/地图问题,我觉得addPosition方法做的太多了; calculate the key, creates the actual item, puts it in a map.计算密钥,创建实际项目,将其放入 map。 If you at least delegate the item creation, you can use proper mocks to test this.如果您至少委托项目创建,则可以使用适当的模拟来测试这一点。

class Administration {
    ItemCreator creator;
    StorageItem add(...) {
       StorageItem item = creator.create(...);
       map.store(item.getPosition(), item);
       return item;
    }
    void inspect(Position position) {
       StorageItem item = map.get(position);
       item.getCargo().inspect();
    }
}

// test
void testAdd() {
    when(creator.create(any(), ...)).thenReturn(item);
    when(item.getPosition()).thenReturn(position);
    admin.add(...);
    verify(creator).create(...);
    verify(map).store(position, item);
}
void testInspect() {
    item = mock(StorageItem.class);
    cargo = mock(Cargo.class);
    when(item.getPosition()).thenReturn(position);
    when(item.getCargo()).thenReturn(cargo);
    when(map.get(position)).thenReturn(item);

    admin.inspect(item);

    verify(map).get(position); // check map was queried
    verify(item).getPosition();  // check item's position was used
    verify(item).getCargo();  // check cargo was retrieved
    verify(cargo).inspect();   // check inspect was performed (the only really important check)
}

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

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