字符串序列化单元测试失败

时间:2018-08-01 12:07:49

标签: java string serialization junit

运行Junit测试String序列化后,它失败了,并给了我以下结果:

预期:"netmodel"
实际:"l"

序列化方法如下

public static void serializeString(String objectToSerialize, OutputStream outputStream) {
    byte[] bytesArr = objectToSerialize.getBytes();
    serializeInt(bytesArr.length, outputStream);
    try {

        outputStream.write(bytesArr);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

我的反序列化方法如下

public static String deserializeString(InputStream inputStream) {
String deserializeObject = "";
char asciiToChar;
int stringByteArrayLength = deserializeInt(inputStream);
byte[] databytesArr = new byte[stringByteArrayLength];

try {
  inputStream.read(databytesArr, 0, stringByteArrayLength);
}
catch (IOException e) {
  e.printStackTrace();
}

for (int i = 0; i < databytesArr.length; i++) {
  asciiToChar = (char) databytesArr[i];
  deserializeObject = "" + Character.toString(asciiToChar);
}
return deserializeObject;
} 

最后,我编写了如下的单元测试

public class StringSerializerTest {

  private InputStream iStream;
  private ByteArrayOutputStream oStream;

  @Before
  public void init() {
    oStream = new ByteArrayOutputStream();
  }

  String serialzeAndDeserializeObject(String stringValue) {
    OutputStreamUtil.serializeString(stringValue, oStream);
    iStream = new ByteArrayInputStream(oStream.toByteArray());
    return InputStreamUtil.deserializeString(iStream);
  }

  @Test
  public void equals_equal() {
    String stringValue = "netmodel";
    String deserializedStringValue = serialzeAndDeserializeObject(stringValue);
    assertThat(deserializedStringValue).isEqualTo(stringValue);
  }
}

怎么了?以及如何解决?

2 个答案:

答案 0 :(得分:2)

您将在每次迭代{p>时重新分配deserializeObject的整个值

for (int i = 0; i < databytesArr.length; i++) {
    asciiToChar = (char) databytesArr[i];
    deserializeObject = "" + Character.toString(asciiToChar);
}

这只会导致最后一个字符(在这种情况下为l)存储在deserializeObject中。此循环应将下一个字符追加deserializeObject,如下所示:

for (int i = 0; i < databytesArr.length; i++) {
    asciiToChar = (char) databytesArr[i];
    deserializeObject += Character.toString(asciiToChar);
}

更正后的反序列化逻辑为:

public static String deserializeString(InputStream inputStream) {
    String deserializeObject = "";
    char asciiToChar;
    int stringByteArrayLength = deserializeInt(inputStream);
    byte[] databytesArr = new byte[stringByteArrayLength];

    try {
        inputStream.read(databytesArr, 0, stringByteArrayLength);
    }
    catch (IOException e) {
        e.printStackTrace();
    }

    for (int i = 0; i < databytesArr.length; i++) {
        asciiToChar = (char) databytesArr[i];
        deserializeObject += Character.toString(asciiToChar);
    }
    return deserializeObject;
} 

答案 1 :(得分:1)

该错误已经由Justin Albano报告。 但是,还要注意非ASCII字符串:例如特殊字符。

类似以下内容。还应在末端关闭以确保在缓冲流的情况下冲洗。从理论上讲,读取只能产生阵列的非阻塞部分。 DataOutputStream有很好的方法,尽管您似乎可以进行自己的序列化。

public static void serializeString(String objectToSerialize, OutputStream outputStream)
        throws IOException {
    byte[] bytesArr = objectToSerialize.getBytes(StandardCharsets.UTF_8);
    serializeInt(bytesArr.length, outputStream);
    outputStream.write(bytesArr);
}

public static String deserializeString(InputStream inputStream)
        throws IOException {
    int stringByteArrayLength = deserializeInt(inputStream);
    byte[] databytesArr = new byte[stringByteArrayLength];
    readFully(inputStream, databytesArr);
    return new String(databytesArr, StandardCharsets.UTF_8);
}

private static void readFully(InputStream inputStream, byte[] bytes) throws IOException {
    int i = 0;
    while (i < bytes.length) {
        int nread = inputStream.read(bytes, i, bytes.length - i);
        if (nread <= 0) {
            throw new IOException("Premature EOF");
        }
        i += nread;
    }
}

请注意,StandardCharsets不在Android SDK中,而仅在标准Java中。

相关问题