我试图理解为什么使用 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());
...
我在这里可能是错的,因为编写 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);