Skip to content

Add test coverage for serialization/deserialization for upcoming refactoring#1806

Merged
jeandersonbc merged 1 commit intomainfrom
prep-work-pre-refactoring
Mar 27, 2026
Merged

Add test coverage for serialization/deserialization for upcoming refactoring#1806
jeandersonbc merged 1 commit intomainfrom
prep-work-pre-refactoring

Conversation

@jeandersonbc
Copy link
Copy Markdown
Contributor

Description

In the scope of JAXB migration, we need some sanity check to verify that the changes will work.
This is not a full complete set, but I sampled a few classes to add coverage.

It would be helpful to get some feedback about the tests and whether we could improve something for the upcoming work.

Tested scenarios

  • simple serialization and deserialization of some impacted classes

@jeandersonbc jeandersonbc self-assigned this Mar 26, 2026
@jeandersonbc jeandersonbc requested review from a team as code owners March 26, 2026 16:37
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds unit tests for various Nexo model classes and a resource-loading utility to verify serialization and deserialization. The feedback suggests optimizing performance by using a static Gson instance and enhancing test maintainability by implementing equals and hashCode methods for more comprehensive round-trip validation.

@Test
public void testShouldSerializeAndDeserializeFromMockFile() throws IOException {
String mockJson = NexoTestUtils.readResource("mocks/terminal-api/abort-request.json");
Gson terminalApiGson = TerminalAPIGsonBuilder.create();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Gson object is created within the test method. Since Gson instances are thread-safe and their creation can be expensive, it's a good practice to create it only once per class. Consider making terminalApiGson a private static final field in the AbortRequestTest class. This improves performance and code clarity.

Comment on lines +52 to +67
assertEquals(deserializedAbortRequest.getAbortReason(), roundTripAbortRequest.getAbortReason());
assertEquals(
deserializedAbortRequest.getMessageReference().getServiceID(),
roundTripAbortRequest.getMessageReference().getServiceID());
assertEquals(
deserializedAbortRequest.getMessageReference().getDeviceID(),
roundTripAbortRequest.getMessageReference().getDeviceID());
assertEquals(
deserializedAbortRequest.getMessageReference().getSaleID(),
roundTripAbortRequest.getMessageReference().getSaleID());
assertEquals(
deserializedAbortRequest.getMessageReference().getPOIID(),
roundTripAbortRequest.getMessageReference().getPOIID());
assertEquals(
deserializedAbortRequest.getDisplayOutput().getInfoQualify(),
roundTripAbortRequest.getDisplayOutput().getInfoQualify());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The round-trip validation is done by asserting a subset of the object's properties. This is brittle and incomplete. For example, MessageReference.MessageCategory is asserted during the initial deserialization but not in this round-trip check.

A more robust and maintainable approach would be to implement equals() and hashCode() methods on the AbortRequest class and its nested objects. This would allow you to replace these multiple assertions with a single, comprehensive check:

assertEquals(deserializedAbortRequest, roundTripAbortRequest);

This ensures that all fields are compared, making the test more thorough and easier to maintain when new fields are added to the model.

Suggested change
assertEquals(deserializedAbortRequest.getAbortReason(), roundTripAbortRequest.getAbortReason());
assertEquals(
deserializedAbortRequest.getMessageReference().getServiceID(),
roundTripAbortRequest.getMessageReference().getServiceID());
assertEquals(
deserializedAbortRequest.getMessageReference().getDeviceID(),
roundTripAbortRequest.getMessageReference().getDeviceID());
assertEquals(
deserializedAbortRequest.getMessageReference().getSaleID(),
roundTripAbortRequest.getMessageReference().getSaleID());
assertEquals(
deserializedAbortRequest.getMessageReference().getPOIID(),
roundTripAbortRequest.getMessageReference().getPOIID());
assertEquals(
deserializedAbortRequest.getDisplayOutput().getInfoQualify(),
roundTripAbortRequest.getDisplayOutput().getInfoQualify());
assertEquals(deserializedAbortRequest, roundTripAbortRequest);

@Test
public void testShouldSerializeAndDeserializeFromMockFile() throws IOException {
String mockJson = NexoTestUtils.readResource("mocks/terminal-api/display-request.json");
Gson terminalApiGson = TerminalAPIGsonBuilder.create();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Gson object is created within the test method. Since Gson instances are thread-safe and their creation can be expensive, it's a good practice to create it only once per class. Consider making terminalApiGson a private static final field in the DisplayRequestTest class. This improves performance and code clarity.

Comment on lines +49 to +57
assertEquals(
"Please present card",
roundTripDisplayRequest
.getDisplayOutput()
.get(0)
.getOutputContent()
.getOutputText()
.get(0)
.getText());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This round-trip validation only checks a single, deeply nested property. This is very incomplete and provides little value. The initial deserialization checks more properties (e.g., Device, InfoQualify).

A more robust and maintainable approach would be to implement equals() and hashCode() methods on the DisplayRequest class and its nested objects. This would allow you to replace this assertion with a single, comprehensive check:

assertEquals(deserializedDisplayRequest, roundTripDisplayRequest);

This ensures that all fields are compared, making the test more thorough and easier to maintain.

    assertEquals(deserializedDisplayRequest, roundTripDisplayRequest);

@Test
public void testShouldSerializeAndDeserializeFromMockFile() throws IOException {
String mockJson = NexoTestUtils.readResource("mocks/terminal-api/login-request.json");
Gson terminalApiGson = TerminalAPIGsonBuilder.create();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Gson object is created within the test method. Since Gson instances are thread-safe and their creation can be expensive, it's a good practice to create it only once per class. Consider making terminalApiGson a private static final field in the LoginRequestTest class. This improves performance and code clarity.

Comment on lines +56 to +66
assertEquals(
deserializedLoginRequest.getDateTime().toString(),
roundTripLoginRequest.getDateTime().toString());
assertEquals(
deserializedLoginRequest.getTokenRequestedType(),
roundTripLoginRequest.getTokenRequestedType());
assertEquals(
deserializedLoginRequest.getCustomerOrderReq(),
roundTripLoginRequest.getCustomerOrderReq());
assertEquals(
deserializedLoginRequest.getPOISerialNumber(), roundTripLoginRequest.getPOISerialNumber());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The round-trip validation is done by asserting a subset of the object's properties. This is brittle and incomplete. Many properties asserted during the initial deserialization (e.g., SaleSoftware details, SaleTerminalData) are not checked here.

A more robust and maintainable approach would be to implement equals() and hashCode() methods on the LoginRequest class and its nested objects. This would allow you to replace these multiple assertions with a single, comprehensive check:

assertEquals(deserializedLoginRequest, roundTripLoginRequest);

This ensures that all fields are compared, making the test more thorough and easier to maintain.

    assertEquals(deserializedLoginRequest, roundTripLoginRequest);

@Test
public void testShouldSerializeAndDeserializeFromMockFile() throws IOException {
String mockJson = NexoTestUtils.readResource("mocks/terminal-api/message-header.json");
Gson terminalApiGson = TerminalAPIGsonBuilder.create();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Gson object is created within the test method. Since Gson instances are thread-safe and their creation can be expensive, it's a good practice to create it only once per class. Consider making terminalApiGson a private static final field in the MessageHeaderTest class. This improves performance and code clarity.

Comment on lines +34 to +47
assertEquals(
deserializedMessageHeader.getProtocolVersion(),
roundTripMessageHeader.getProtocolVersion());
assertEquals(
deserializedMessageHeader.getMessageClass(), roundTripMessageHeader.getMessageClass());
assertEquals(
deserializedMessageHeader.getMessageCategory(),
roundTripMessageHeader.getMessageCategory());
assertEquals(
deserializedMessageHeader.getMessageType(), roundTripMessageHeader.getMessageType());
assertEquals(deserializedMessageHeader.getServiceID(), roundTripMessageHeader.getServiceID());
assertEquals(deserializedMessageHeader.getDeviceID(), roundTripMessageHeader.getDeviceID());
assertEquals(deserializedMessageHeader.getSaleID(), roundTripMessageHeader.getSaleID());
assertEquals(deserializedMessageHeader.getPOIID(), roundTripMessageHeader.getPOIID());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While these assertions cover all properties of MessageHeader, the test can be made more concise and maintainable.

By implementing equals() and hashCode() on the MessageHeader class, you can replace all these individual assertions with a single line:

assertEquals(deserializedMessageHeader, roundTripMessageHeader);

This approach is cleaner and scales better if new fields are added to MessageHeader in the future.

    assertEquals(deserializedMessageHeader, roundTripMessageHeader);

@Test
public void testShouldSerializeAndDeserializeFromMockFile() throws IOException {
String mockJson = NexoTestUtils.readResource("mocks/terminal-api/message-reference.json");
Gson terminalApiGson = TerminalAPIGsonBuilder.create();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The Gson object is created within the test method. Since Gson instances are thread-safe and their creation can be expensive, it's a good practice to create it only once per class. Consider making terminalApiGson a private static final field in the MessageReferenceTest class. This improves performance and code clarity.

Comment on lines +35 to +43
assertEquals(
deserializedMessageReference.getMessageCategory(),
roundTripMessageReference.getMessageCategory());
assertEquals(
deserializedMessageReference.getServiceID(), roundTripMessageReference.getServiceID());
assertEquals(
deserializedMessageReference.getDeviceID(), roundTripMessageReference.getDeviceID());
assertEquals(deserializedMessageReference.getSaleID(), roundTripMessageReference.getSaleID());
assertEquals(deserializedMessageReference.getPOIID(), roundTripMessageReference.getPOIID());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While these assertions cover all properties of MessageReference, the test can be made more concise and maintainable.

By implementing equals() and hashCode() on the MessageReference class, you can replace all these individual assertions with a single line:

assertEquals(deserializedMessageReference, roundTripMessageReference);

This approach is cleaner and scales better if new fields are added to MessageReference in the future.

    assertEquals(deserializedMessageReference, roundTripMessageReference);

Copy link
Copy Markdown
Contributor

@gcatanese gcatanese left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the Gemini comments are not critical, we can go ahead

@jeandersonbc jeandersonbc added this pull request to the merge queue Mar 27, 2026
Merged via the queue into main with commit ca74969 Mar 27, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants