伪造 Confluent .NET Kafka 消费者
Faking Confluent .NET Kafka consumers
环境:.NET 4.5。
FakeItEasy : 4.0.0
我正在尝试创建一个 Kafka 消费者的假对象,下面是我使用的语法:
var fakeconsumer = A.Fake<Consumer<Null, string>>((x => x.WithArgumentsForConstructor(() => new Consumer<Null, string>(A.Dummy<IEnumerable<KeyValuePair<string, object>>>(), A.Dummy<IDeserializer<Null>>(), A.Dummy<StringDeserializer>()))));
Kafka客户端的代码在这里:https://github.com/confluentinc/confluent-kafka-dotnet/blob/master/src/Confluent.Kafka/Consumer.cs
如您所见,我正在使用构造函数所需的正确参数调用 Fake 调用。但是我不断收到以下错误消息:"No constructor matches the passed arguments for constructor.".
非常感谢任何帮助。
谢谢
编辑:
at FakeItEasy.Creation.CastleDynamicProxy.CastleDynamicProxyGenerator.CreateProxyGeneratorResult(Type typeOfProxy, ProxyGenerationOptions options, IEnumerable1 additionalInterfacesToImplement, IEnumerable
1 argumentsForConstructor, IFakeCallProcessorProvider fakeCallProcessorProvider) in C:\projects\fakeiteasy\src\FakeItEasy\Creation\CastleDynamicProxy\CastleDynamicProxyGenerator.cs:line 125
at FakeItEasy.Creation.CastleDynamicProxy.CastleDynamicProxyGenerator.GenerateProxy(Type typeOfProxy, ProxyGenerationOptions options, IEnumerable1 additionalInterfacesToImplement, IEnumerable
1 argumentsForConstructor, IFakeCallProcessorProvider fakeCallProcessorProvider) in C:\projects\fakeiteasy\src\FakeItEasy\Creation\CastleDynamicProxy\CastleDynamicProxyGenerator.cs:line 86
at FakeItEasy.Creation.FakeObjectCreator.GenerateProxy(Type typeOfFake, IProxyOptions proxyOptions, IEnumerable1 argumentsForConstructor) in C:\projects\fakeiteasy\src\FakeItEasy\Creation\FakeObjectCreator.cs:line 113
at FakeItEasy.Creation.FakeObjectCreator.CreateFake(Type typeOfFake, IProxyOptions proxyOptions, DummyCreationSession session, IDummyValueResolver resolver, Boolean throwOnFailure) in C:\projects\fakeiteasy\src\FakeItEasy\Creation\FakeObjectCreator.cs:line 36
at FakeItEasy.Creation.DefaultFakeAndDummyManager.CreateFake(Type typeOfFake, Action
1 optionsBuilder) in C:\projects\fakeiteasy\src\FakeItEasy\Creation\DefaultFakeAndDummyManager.cs:line 41
at FakeItEasy.A.Fake[T](Action`1 optionsBuilder) in C:\projects\fakeiteasy\src\FakeItEasy\A.cs:line 47
我不是 Kafka 消费者 class 方面的专家,但看起来您是这样调用它的:
Consumer<Null, string>
但我能在代码中找到的唯一构造函数是:
public Consumer(
IEnumerable<KeyValuePair<string, object>> config)
public Consumer(
IEnumerable<KeyValuePair<string, object>> config,
IDeserializer<TKey> keyDeserializer,
IDeserializer<TValue> valueDeserializer)
所以没有匹配。看起来您想使用第一个,所以您缺少 IEnumerable 部分。
我相信我已经重现了你的问题。这是我看到的完整异常:
FakeItEasy.Core.FakeCreationException :
Failed to create fake of type Confluent.Kafka.Consumer`2[Confluent.Kafka.Null,System.String] with the specified arguments for the constructor:
No constructor matches the passed arguments for constructor.
An exception of type System.ArgumentException was caught during this call. Its message was:
'group.id' configuration parameter is required and was not specified.
at Confluent.Kafka.Consumer..ctor(IEnumerable`1 config)
at Confluent.Kafka.Consumer`2..ctor(IEnumerable`1 config, IDeserializer`1 keyDeserializer, IDeserializer`1 valueDeserializer)
at Castle.Proxies.Consumer`2Proxy..ctor(IInterceptor[] , IEnumerable`1 , IDeserializer`1 , IDeserializer`1 )
at FakeItEasy.Core.DefaultExceptionThrower.ThrowFailedToGenerateProxyWithArgumentsForConstructor(Type typeOfFake, String reasonForFailure)
at FakeItEasy.Creation.FakeObjectCreator.AssertThatProxyWasGeneratedWhenArgumentsForConstructorAreSpecified(Type typeOfFake, ProxyGeneratorResult result, IProxyOptions proxyOptions)
at FakeItEasy.Creation.FakeObjectCreator.CreateFake(Type typeOfFake, IProxyOptions proxyOptions, DummyCreationSession session, IDummyValueResolver resolver, Boolean throwOnFailure)
at FakeItEasy.Creation.DefaultFakeAndDummyManager.CreateFake(Type typeOfFake, Action`1 optionsBuilder)
at FakeItEasy.A.Fake[T](Action`1 optionsBuilder)
Kafka.cs(14,0): at FakeItEasyQuestions2015.Kafka.MakeConsumer()
可以看到FakeItEasy本身在调用Consumer
class的构造函数时遇到了异常:
An exception of type System.ArgumentException was caught during this call. Its message was:
'group.id' configuration parameter is required and was not specified.
这是从 Consumer constructor on line 756:
抛出的
if (config.FirstOrDefault(prop => string.Equals(prop.Key, "group.id", StringComparison.Ordinal)).Value == null)
{
throw new ArgumentException("'group.id' configuration parameter is required and was not specified.");
}
好像
Consumer(IEnumerable<KeyValuePair<string, object>> config,
IDeserializer<TKey> keyDeserializer,
IDeserializer<TValue> valueDeserializer)`
对其输入有一些未满足的要求。特别是,它似乎需要 config
来包含一个键为 "group.id" 的元素。如果我将您的代码更改为
var fakeconsumer = A.Fake<Consumer<Null, string>>(
(x => x.WithArgumentsForConstructor(
() => new Consumer<Null, string>(new [] { new KeyValuePair<string, object>("group.id", "hippo")},
A.Dummy<IDeserializer<Null>>(),
A.Dummy<StringDeserializer>()))));
造假
我注意到您交叉发布到 FakeItEasy Issue 1176。我会在那里做个笔记来这里回答这个问题。
不是 100% 与原始问题相关,而是在我的图书馆中(Silverback:https://github.com/BEagle1984/silverback) I have a mocked in-memory implementation of the Confluent.Kafka library, that allows for kinda sophisticated integration tests. See some simple examples: https://silverback-messaging.net/concepts/broker/testing.html。
只是给你一个想法:
[Fact]
public async Task SampleTest()
{
// Arrange
var testingHelper = _factory.Server.Host.Services
.GetRequiredService<IKafkaTestingHelper>();
var producer = testingHelper.Broker
.GetProducer(new KafkaProducerEndpoint("tst-topic"));
// Act
await producer.ProduceAsync(new TestMessage { Content = "abc" });
await testingHelper.WaitUntilAllMessagesAreConsumedAsync();
// Assert
testingHelper.Spy.OutboundEnvelopes.Should().HaveCount(1);
testingHelper.Spy.InboundEnvelopes.Should().HaveCount(1);
testingHelper.Spy.InboundEnvelopes[0].Message.As<TestMessage>
.Content.Should().Be("abc");
}
实现并不复杂,但它支持分区和重新平衡机制的模拟。
查看实现:https://github.com/BEagle1984/silverback/tree/master/src/Silverback.Integration.Kafka.Testing/Messaging/Broker/Kafka
环境:.NET 4.5。 FakeItEasy : 4.0.0
我正在尝试创建一个 Kafka 消费者的假对象,下面是我使用的语法:
var fakeconsumer = A.Fake<Consumer<Null, string>>((x => x.WithArgumentsForConstructor(() => new Consumer<Null, string>(A.Dummy<IEnumerable<KeyValuePair<string, object>>>(), A.Dummy<IDeserializer<Null>>(), A.Dummy<StringDeserializer>()))));
Kafka客户端的代码在这里:https://github.com/confluentinc/confluent-kafka-dotnet/blob/master/src/Confluent.Kafka/Consumer.cs
如您所见,我正在使用构造函数所需的正确参数调用 Fake 调用。但是我不断收到以下错误消息:"No constructor matches the passed arguments for constructor.".
非常感谢任何帮助。
谢谢
编辑:
at FakeItEasy.Creation.CastleDynamicProxy.CastleDynamicProxyGenerator.CreateProxyGeneratorResult(Type typeOfProxy, ProxyGenerationOptions options, IEnumerable
1 additionalInterfacesToImplement, IEnumerable
1 argumentsForConstructor, IFakeCallProcessorProvider fakeCallProcessorProvider) in C:\projects\fakeiteasy\src\FakeItEasy\Creation\CastleDynamicProxy\CastleDynamicProxyGenerator.cs:line 125 at FakeItEasy.Creation.CastleDynamicProxy.CastleDynamicProxyGenerator.GenerateProxy(Type typeOfProxy, ProxyGenerationOptions options, IEnumerable1 additionalInterfacesToImplement, IEnumerable
1 argumentsForConstructor, IFakeCallProcessorProvider fakeCallProcessorProvider) in C:\projects\fakeiteasy\src\FakeItEasy\Creation\CastleDynamicProxy\CastleDynamicProxyGenerator.cs:line 86 at FakeItEasy.Creation.FakeObjectCreator.GenerateProxy(Type typeOfFake, IProxyOptions proxyOptions, IEnumerable1 argumentsForConstructor) in C:\projects\fakeiteasy\src\FakeItEasy\Creation\FakeObjectCreator.cs:line 113 at FakeItEasy.Creation.FakeObjectCreator.CreateFake(Type typeOfFake, IProxyOptions proxyOptions, DummyCreationSession session, IDummyValueResolver resolver, Boolean throwOnFailure) in C:\projects\fakeiteasy\src\FakeItEasy\Creation\FakeObjectCreator.cs:line 36 at FakeItEasy.Creation.DefaultFakeAndDummyManager.CreateFake(Type typeOfFake, Action
1 optionsBuilder) in C:\projects\fakeiteasy\src\FakeItEasy\Creation\DefaultFakeAndDummyManager.cs:line 41 at FakeItEasy.A.Fake[T](Action`1 optionsBuilder) in C:\projects\fakeiteasy\src\FakeItEasy\A.cs:line 47
我不是 Kafka 消费者 class 方面的专家,但看起来您是这样调用它的:
Consumer<Null, string>
但我能在代码中找到的唯一构造函数是:
public Consumer(
IEnumerable<KeyValuePair<string, object>> config)
public Consumer(
IEnumerable<KeyValuePair<string, object>> config,
IDeserializer<TKey> keyDeserializer,
IDeserializer<TValue> valueDeserializer)
所以没有匹配。看起来您想使用第一个,所以您缺少 IEnumerable 部分。
我相信我已经重现了你的问题。这是我看到的完整异常:
FakeItEasy.Core.FakeCreationException :
Failed to create fake of type Confluent.Kafka.Consumer`2[Confluent.Kafka.Null,System.String] with the specified arguments for the constructor:
No constructor matches the passed arguments for constructor.
An exception of type System.ArgumentException was caught during this call. Its message was:
'group.id' configuration parameter is required and was not specified.
at Confluent.Kafka.Consumer..ctor(IEnumerable`1 config)
at Confluent.Kafka.Consumer`2..ctor(IEnumerable`1 config, IDeserializer`1 keyDeserializer, IDeserializer`1 valueDeserializer)
at Castle.Proxies.Consumer`2Proxy..ctor(IInterceptor[] , IEnumerable`1 , IDeserializer`1 , IDeserializer`1 )
at FakeItEasy.Core.DefaultExceptionThrower.ThrowFailedToGenerateProxyWithArgumentsForConstructor(Type typeOfFake, String reasonForFailure)
at FakeItEasy.Creation.FakeObjectCreator.AssertThatProxyWasGeneratedWhenArgumentsForConstructorAreSpecified(Type typeOfFake, ProxyGeneratorResult result, IProxyOptions proxyOptions)
at FakeItEasy.Creation.FakeObjectCreator.CreateFake(Type typeOfFake, IProxyOptions proxyOptions, DummyCreationSession session, IDummyValueResolver resolver, Boolean throwOnFailure)
at FakeItEasy.Creation.DefaultFakeAndDummyManager.CreateFake(Type typeOfFake, Action`1 optionsBuilder)
at FakeItEasy.A.Fake[T](Action`1 optionsBuilder)
Kafka.cs(14,0): at FakeItEasyQuestions2015.Kafka.MakeConsumer()
可以看到FakeItEasy本身在调用Consumer
class的构造函数时遇到了异常:
An exception of type System.ArgumentException was caught during this call. Its message was:
'group.id' configuration parameter is required and was not specified.
这是从 Consumer constructor on line 756:
抛出的if (config.FirstOrDefault(prop => string.Equals(prop.Key, "group.id", StringComparison.Ordinal)).Value == null)
{
throw new ArgumentException("'group.id' configuration parameter is required and was not specified.");
}
好像
Consumer(IEnumerable<KeyValuePair<string, object>> config,
IDeserializer<TKey> keyDeserializer,
IDeserializer<TValue> valueDeserializer)`
对其输入有一些未满足的要求。特别是,它似乎需要 config
来包含一个键为 "group.id" 的元素。如果我将您的代码更改为
var fakeconsumer = A.Fake<Consumer<Null, string>>(
(x => x.WithArgumentsForConstructor(
() => new Consumer<Null, string>(new [] { new KeyValuePair<string, object>("group.id", "hippo")},
A.Dummy<IDeserializer<Null>>(),
A.Dummy<StringDeserializer>()))));
造假
我注意到您交叉发布到 FakeItEasy Issue 1176。我会在那里做个笔记来这里回答这个问题。
不是 100% 与原始问题相关,而是在我的图书馆中(Silverback:https://github.com/BEagle1984/silverback) I have a mocked in-memory implementation of the Confluent.Kafka library, that allows for kinda sophisticated integration tests. See some simple examples: https://silverback-messaging.net/concepts/broker/testing.html。
只是给你一个想法:
[Fact]
public async Task SampleTest()
{
// Arrange
var testingHelper = _factory.Server.Host.Services
.GetRequiredService<IKafkaTestingHelper>();
var producer = testingHelper.Broker
.GetProducer(new KafkaProducerEndpoint("tst-topic"));
// Act
await producer.ProduceAsync(new TestMessage { Content = "abc" });
await testingHelper.WaitUntilAllMessagesAreConsumedAsync();
// Assert
testingHelper.Spy.OutboundEnvelopes.Should().HaveCount(1);
testingHelper.Spy.InboundEnvelopes.Should().HaveCount(1);
testingHelper.Spy.InboundEnvelopes[0].Message.As<TestMessage>
.Content.Should().Be("abc");
}
实现并不复杂,但它支持分区和重新平衡机制的模拟。 查看实现:https://github.com/BEagle1984/silverback/tree/master/src/Silverback.Integration.Kafka.Testing/Messaging/Broker/Kafka