RMI 测试在隔离中通过,但与其他测试一起运行时失败并出现 UnmarshalException

问题描述 投票:0回答:1

我试图理解为什么使用 RMI 的特定测试方法在单独运行时会通过,但在与也使用 RMI 的其他测试一起运行时会失败。两种情况的测试结构相同。

...

  @BeforeClass
  public static void beforeTest() throws Exception {
    try {
      System.setProperty(Constants.JAVA_RMI_TEST_PORT_ENVIRONMENT, TestEnvironment.getPort());
      dataFactory.register();
      await().atMost(5, TimeUnit.SECONDS);
      client = DataFactoryClient.getInstance(TestEnvironment.getDomain(), TestEnvironment.getPort());
    } catch (RemoteException e) {
      throw new RuntimeException(e);
    } catch (NotBoundException e) {
      throw new RuntimeException(e);
    }
  }

  @AfterClass
  public static void afterAll() {
    dataFactory.release();
  }


  @Test
  public void testSimpleSave() throws Exception {
    EntityStore entityStore = client.getEntityStore();
    Assert.assertNotNull(entityStore);

    DataFactoryEntity entity = new DataFactoryEntityBuilder()
            .environment(TestEnvironment.getEnvironment())
            .entityType("Foo")
            .putPropertyMap("foo", "bar")
            .build();

    DataFactoryEntity dataFactoryEntity = entityStore.saveEntity(entity).get();
    Assert.assertNotNull(dataFactoryEntity);
    Assert.assertNotNull(dataFactoryEntity.entityId());
    Assert.assertEquals("bar", dataFactoryEntity.propertyMap().get("foo"));
  }
public class EntityStoreClientImpl implements EntityStore {
  @Override public Option<DataFactoryEntity> saveEntity(@NotNull DataFactoryEntity entity)
      throws DataFactoryException, NotBoundException, RemoteException {
    return getEntityStore().saveEntity(entity);
  }
}

如果不单独运行,测试方法

testSimpleSave
将会失败。当与其他测试一起运行时,它会抛出:

java.rmi.UnmarshalException: error unmarshalling return; nested exception is: 
    java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: ....datafactory.database.impl.DatabaseManagerImpl

    at sun.rmi.registry.RegistryImpl_Stub.lookup(RegistryImpl_Stub.java:130)
    at ....datafactory.repositories.impl.EntityStoreClientImpl.getEntityStore(EntityStoreClientImpl.java:108)
    at ....datafactory.repositories.impl.EntityStoreClientImpl.saveEntity(EntityStoreClientImpl.java:56)
    at ....datafactory.DataFactoryClientTest.testSimpleSave(DataFactoryClientTest.java:75

它不应该像其他单元测试一样序列化

DatabaseManagerImpl
(无论如何这并不意味着)。令人费解的是为什么这个特定的测试试图序列化它。

可以在此处检查整个测试代码的详细程度。

我需要一些帮助,我将不胜感激!

更新:

这里是可以通过的类似测试的快速参考:

  @Test
  public void testNearbyConditionWithGeoHash() throws Exception {
    String environment = TestEnvironment.getEnvironment();
    EntityStore entityStore = DataFactoryClient.getInstance(TestEnvironment.getDomain(), TestEnvironment.getPort()).getEntityStore();

    DataFactoryEntity firstLocation = new DataFactoryEntityBuilder()
        .environment(environment)
        .entityType("Room")
        .putPropertyMap("address", "Room 123, 456 Street, 789 Avenue")
        .putPropertyMap("geoLocation", new GeoHash(120.976171, 14.580919).toString())
        .build();
    firstLocation = entityStore.saveEntity(firstLocation).get();
    assertNotNull(firstLocation.entityId());
...
java rmi
1个回答
0
投票

我在这里可能是错的,因为编写 RMI 服务器已经有一段时间了,很难看出你的代码做了什么,所以如果这没有帮助,我会删除它。

RMI 依赖于序列化,因此任何非瞬态成员字段都是客户端和服务器之间传输的候选者。我看到

EntityStoreImpl
包含对
DatabaseManager
的非瞬态引用。将 DataFactory 绑定到注册表时,您使用以下实现:

  entityStore = new EntityStoreImpl(DatabaseManagerImpl.getInstance(), LuceneIndexerImpl.getInstance());
  registry.rebind(EntityStore.class.getName(), entityStore);

通常我希望看到生成的存根,因此不会直接引用实现类:

  EntityStore stub = (EntityStore )UnicastRemoteObject.exportObject(entityStore, 0);
  registry.rebind(EntityStore.class.getName(), stub);
© www.soinside.com 2019 - 2024. All rights reserved.