code: def test_basic_merge(self):
      parent = {
          "py_modules": [
              "http://test.com/test0.zip",
              "s3://path/test1.zip",
          ],
          "working_dir": "gs://path/test2.zip",
          "env_vars": {"test": "val", "trial": "val2"},
          "pip": ["pandas", "numpy"],
          "excludes": ["my_file.txt"],
      }
      original_parent = parent.copy()
  
      child = {
          "py_modules": [],
          "working_dir": "s3://path/test1.zip",
          "env_vars": {"test": "val", "trial": "val2"},
          "pip": ["numpy"],
      }
      original_child = child.copy()
  
      merged = override_runtime_envs_except_env_vars(parent, child)
  
      assert original_parent == parent
      assert original_child == child
      assert merged == {
          "py_modules": [],
          "working_dir": "s3://path/test1.zip",
          "env_vars": {"test": "val", "trial": "val2"},
          "pip": ["numpy"],
          "excludes": ["my_file.txt"],
      }
  
imports: import asyncio
  import json
  import os
  import time
  from unittest.mock import patch
  import numpy
  import pytest
  from fastapi.encoders import jsonable_encoder
  import ray
  from ray import serve
  from ray._private.resource_spec import HEAD_NODE_RESOURCE_NAME
  from ray._private.test_utils import wait_for_condition
  from ray.serve._private.test_utils import MockTimer
  from ray.serve._private.utils import MetricsPusher, calculate_remaining_timeout, get_all_live_placement_group_names, get_current_actor_id, get_head_node_id, is_running_in_asyncio_loop, merge_dict, msgpack_deserialize, msgpack_serialize, override_runtime_envs_except_env_vars, serve_encoders, snake_to_camel_case
  from ray.serve.tests.common.remote_uris import TEST_DAG_PINNED_URI, TEST_DEPLOY_GROUP_PINNED_URI
label_desc: Use image node_id 5 for calling the TestOverrideRuntimeEnvsExceptEnvVars obj's underlying member method code with example usage: obj.test_basic_merge() without return types