{"record":{"id":"bfa2ed2208a862c1","repo":"apache/beam","slug":"both-pubsubtestclientfactory-and-clock-need-to-be-specified","errorCode":null,"errorMessage":"Both PubsubTestClientFactory and Clock need to be specified for testing, but only one is provided","messagePattern":"Both PubsubTestClientFactory and Clock need to be specified for testing, but only one is provided","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/pubsub/PubsubReadSchemaTransformProvider.java","lineNumber":273,"sourceCode":"              ? PubsubIO.readMessages()\n              : PubsubIO.readMessagesWithAttributes();\n      String topic = configuration.getTopic();\n      if (topic != null && !topic.isEmpty()) {\n        pubsubRead = pubsubRead.fromTopic(topic);\n      } else {\n        String subscription = configuration.getSubscription();\n        pubsubRead =\n            pubsubRead.fromSubscription(\n                checkArgumentNotNull(\n                    subscription, \"Either topic or subscription must be specified\"));\n      }\n      final PubsubTestClientFactory clientFactory = this.clientFactory;\n      final Clock clock = this.clock;\n      if (clientFactory != null && clock != null) {\n        pubsubRead = pubsubRead.withClientFactory(clientFactory);\n        pubsubRead = clientFactory.setClock(pubsubRead, clock);\n      } else if (clientFactory != null || clock != null) {\n        throw new IllegalArgumentException(\n            \"Both PubsubTestClientFactory and Clock need to be specified for testing, but only one is provided\");\n      }\n      String idAttribute = configuration.getIdAttribute();\n      if (idAttribute != null && !idAttribute.isEmpty()) {\n        pubsubRead = pubsubRead.withIdAttribute(idAttribute);\n      }\n      String timestampAttribute = configuration.getTimestampAttribute();\n      if (timestampAttribute != null && !timestampAttribute.isEmpty()) {\n        pubsubRead = pubsubRead.withTimestampAttribute(timestampAttribute);\n      }\n      return pubsubRead;\n    }\n\n    @Override\n    public PCollectionRowTuple expand(PCollectionRowTuple input) {\n      PubsubIO.Read<PubsubMessage> pubsubRead = buildPubsubRead();\n      PubsubReadSchemaTransformConfiguration.ErrorHandling errorHandling =\n          configuration.getErrorHandling();","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/pubsub/PubsubReadSchemaTransformProvider.java#L255-L291","documentation":"In buildPubsubRead, test hooks (a PubsubTestClientFactory and a Clock) must be supplied as a pair. If exactly one of clientFactory or clock is set on the provider, it throws, because the test client cannot operate correctly with only one of the two.","triggerScenarios":"Constructing PubsubReadSchemaTransformProvider (e.g. via its builder) with only clientFactory set or only clock set, then calling from()/pubsubRead() to build the read transform — typically in unit tests.","commonSituations":"Test code that was updated to set the clock but forgot the client factory (or vice versa); refactoring that moved one of the two settings; partially copied test setup from another test class.","solutions":["Set BOTH clientFactory and clock on the provider when testing.","If not testing against a fake Pubsub client, clear BOTH fields so the production client path is used.","Review test setup helpers to ensure the pair is always set together."],"exampleFix":"// before\nprovider = new PubsubReadSchemaTransformProvider().withClientFactory(factory); // clock missing\n// after\nprovider = new PubsubReadSchemaTransformProvider().withClientFactory(factory).withClock(clock);","handlingStrategy":"validation","validationCode":"if ((provider.clientFactory != null) != (provider.clock != null)) { throw new IllegalStateException(\"Set both PubsubTestClientFactory and Clock for testing, or neither\"); }","typeGuard":null,"tryCatchPattern":"try { return provider.from(cfg); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"PubsubTestClientFactory\")) { /* complete the test pair */ } throw e; }","preventionTips":["Encapsulate test setup in one helper that always sets clientFactory and clock together.","Centralize fake-client construction so the pair cannot drift apart during refactors."],"tags":["java","apache-beam","pubsub","testing"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}