test: virual attribute parsing on records

Co-authored-by-AI: IBM Bob (1.126.0+bob2.1.0)
diff --git a/src/test/java/org/eclipse/yasson/records/RecordTest.java b/src/test/java/org/eclipse/yasson/records/RecordTest.java
index 3c1b72a..250a001 100644
--- a/src/test/java/org/eclipse/yasson/records/RecordTest.java
+++ b/src/test/java/org/eclipse/yasson/records/RecordTest.java
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2021, 2025 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v. 2.0 which is available at
@@ -21,7 +22,9 @@
 import org.junit.jupiter.api.Test;
 
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
@@ -119,4 +122,72 @@
                 .fromJson(expected, new TestTypeToken<CarWithGenerics<Color>>() {}.getType());
         assertThat(deserialized, is(car));  
     }
+    // -----------------------------------------------------------------
+    // isVirtualAccessorMethod — virtual (computed) record attributes
+    // -----------------------------------------------------------------
+
+    /**
+     * A record's zero-parameter, non-void method whose name does not match any
+     * component must be serialized as a JSON property (virtual attribute).
+     */
+    @Test
+    public void testRecordVirtualAttributeIsIncludedInJson() {
+        RecordWithVirtualAttributes record = new RecordWithVirtualAttributes("skoda", "green");
+        String json = Jsonbs.defaultJsonb.toJson(record);
+
+        assertThat(json, containsString("\"displayName\":\"skoda (green)\""));
+        assertThat(json, containsString("\"componentCount\":2"));
+    }
+
+    /**
+     * The standard record components must still appear alongside the virtual attributes.
+     */
+    @Test
+    public void testRecordVirtualAttributeDoesNotSuppressComponents() {
+        RecordWithVirtualAttributes record = new RecordWithVirtualAttributes("skoda", "green");
+        String json = Jsonbs.defaultJsonb.toJson(record);
+
+        assertThat(json, containsString("\"type\":\"skoda\""));
+        assertThat(json, containsString("\"color\":\"green\""));
+    }
+
+    /**
+     * {@code hashCode()} is explicitly excluded by {@code isVirtualAccessorMethod}
+     * and must not appear in the serialized JSON.
+     */
+    @Test
+    public void testRecordHashCodeMethodIsNotIncludedInJson() {
+        RecordWithVirtualAttributes record = new RecordWithVirtualAttributes("skoda", "green");
+        String json = Jsonbs.defaultJsonb.toJson(record);
+
+        assertThat(json, not(containsString("\"hashCode\"")));
+    }
+
+    /**
+     * {@code toString()} is explicitly excluded by {@code isVirtualAccessorMethod}
+     * and must not appear in the serialized JSON.
+     */
+    @Test
+    public void testRecordToStringMethodIsNotIncludedInJson() {
+        RecordWithVirtualAttributes record = new RecordWithVirtualAttributes("skoda", "green");
+        String json = Jsonbs.defaultJsonb.toJson(record);
+
+        assertThat(json, not(containsString("\"toString\"")));
+    }
+
+    /**
+     * Virtual attributes are read-only; deserialization of the underlying components
+     * must still work correctly even when virtual attribute keys are present in the JSON.
+     * Unknown virtual attribute keys are simply ignored on the way in.
+     */
+    @Test
+    public void testRecordVirtualAttributeIsIgnoredDuringDeserialization() {
+        String json = "{\"type\":\"skoda\",\"color\":\"green\","
+                + "\"displayName\":\"skoda (green)\",\"componentCount\":2}";
+        RecordWithVirtualAttributes deserialized =
+                Jsonbs.defaultJsonb.fromJson(json, RecordWithVirtualAttributes.class);
+
+        assertThat(deserialized.type(), is("skoda"));
+        assertThat(deserialized.color(), is("green"));
+    }
 }
diff --git a/src/test/java/org/eclipse/yasson/records/RecordWithVirtualAttributes.java b/src/test/java/org/eclipse/yasson/records/RecordWithVirtualAttributes.java
new file mode 100644
index 0000000..dfd65f5
--- /dev/null
+++ b/src/test/java/org/eclipse/yasson/records/RecordWithVirtualAttributes.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+package org.eclipse.yasson.records;
+
+/**
+ * A record that exposes virtual (computed) attributes alongside its regular components.
+ * <p>
+ * <ul>
+ *   <li>{@code type} and {@code color} are standard record components.</li>
+ *   <li>{@code displayName()} is a virtual attribute: a zero-parameter, non-void method
+ *       whose name does not match any component — it should appear in the serialized JSON.</li>
+ *   <li>{@code hashCode()} and {@code toString()} are explicitly excluded by
+ *       {@code isVirtualAccessorMethod} and must NOT appear in the JSON.</li>
+ * </ul>
+ */
+public record RecordWithVirtualAttributes(String type, String color) {
+
+    /** Virtual (computed) attribute — should be included in JSON output. */
+    public String displayName() {
+        return type + " (" + color + ")";
+    }
+
+    /** Returns a numeric virtual attribute — should be included in JSON output. */
+    public int componentCount() {
+        return 2;
+    }
+}