'BoDi.ObjectContainerException : Interface cannot be resolved in Specflow test
I have this step in a Specflow
test:
[Then(@"the enriched messages are written to the LC")]
public void ThenTheEnrichedMessagesAreWrittenToTheLC()
{
var LcApplicationOptions = new LcApplicationOptions();
_configuration.GetSection("LcApplication").Bind(LcApplicationOptions);
Subscription sub = new Subscription(LcApplicationOptions.LcVendor, LcApplicationOptions.LcInstrument);
MessageConsumer consumer = new NetMessageConsumer();
// If Client throws an exception via ctor then it probably cant find Config\Fields.json
using (Client c = new Client(LcApplicationOptions.LcHost, _loggerClient, _fieldDictionary, _subscriptionIdGenerator, _iLifetimeScope))
{
int subscriptionId;
c.OnConnected += Client_OnConnected;
c.OnClosed += Client_OnClosed;
// Register the subscription which will connect to LC and login first.
// Any updates for this instrument will be handled by "consumer".
subscriptionId = c.Register(sub, LcApplicationOptions.LcAuthToken, consumer);
// The subscriptionId is also reflected in sub.Id after the call.
Console.WriteLine("hit enter...");
//Console.ReadLine();
// You can unsubscribe like this
c.Unregister(sub.Id);
}
}
When I ran it I got this error:
[xUnit.net 00:02:31.22] System.ArgumentNullException : Value cannot be null. (Parameter 'logger') [xUnit.net 00:02:31.22] Stack Trace: [xUnit.net 00:02:31.22] at Microsoft.Extensions.Logging.LoggerExtensions.Log(ILogger logger, LogLevel logLevel, EventId eventId, Exception exception, String message, Object[] args) [xUnit.net 00:02:31.22] at Microsoft.Extensions.Logging.LoggerExtensions.Log(ILogger logger, LogLevel logLevel, Exception exception, String message, Object[] args) [xUnit.net 00:02:31.22] at Microsoft.Extensions.Logging.LoggerExtensions.LogError(ILogger logger, Exception exception, String message, Object[] args) [xUnit.net 00:02:31.22] at NX.Data.Client.AddRequest(Subscription sub, ConsumerInfo ci, IMessageConsumer msgConsumer) [xUnit.net 00:02:31.22] at NX.Data.Client.Register(Subscription sub, String authToken, IMessageConsumer msgConsumer) [xUnit.net 00:02:31.22]
The problem is that the Client constructor is as follows but I was passing a null for logger
.
public Client(string lcClientAddress, ILogger<Client> logger, IFieldDictionary fieldDictionary, SubscriptionIdGenerator subscriptionIdGenerator, ILifetimeScope scope);
I edited my steps class constructor as follows:
private readonly ILogger<Client> _loggerClient;
public EBSIntegrationTestStepDefinitions(ITestOutputHelper testOutputHelper, ScenarioContext scenarioContext, FeatureContext featureContext, ILogger<Client> loggerClient)
{
_loggerClient = loggerClient;
}
Now when I run my test I get this:
xUnit.net 00:00:01.08] BoDi.ObjectContainerException : Interface cannot be resolved: Microsoft.Extensions.Logging.ILogger
1[[NX.Data.Client, DpNet.Data, Version=0.0.2.178, Culture=neutral, PublicKeyToken=null]] (resolution path: ebs_test_tool.Steps.EBSIntegrationTestStepDefinitions) [xUnit.net 00:00:01.08] Stack Trace: [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.TypeRegistration.<>c__DisplayClass3_0.<ResolvePerContext>b__1() [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.RegistrationWithStrategy.ExecuteWithLock(Object lockObject, Func
1 getter, Func1 factory, ResolutionList resolutionPath) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.TypeRegistration.ResolvePerContext(ObjectContainer container, RegistrationKey keyToResolve, ResolutionList resolutionPath) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.RegistrationWithStrategy.Resolve(ObjectContainer container, RegistrationKey keyToResolve, ResolutionList resolutionPath) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.ResolveObject(RegistrationKey keyToResolve, ResolutionList resolutionPath) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.Resolve(Type typeToResolve, ResolutionList resolutionPath, String name) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.<>c__DisplayClass71_0.<ResolveArguments>b__0(ParameterInfo p) [xUnit.net 00:00:01.08] at System.Linq.Enumerable.SelectArrayIterator
2.ToArray() [xUnit.net 00:00:01.08] at System.Linq.Enumerable.ToArray[TSource](IEnumerable1 source) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.ResolveArguments(IEnumerable
1 parameters, RegistrationKey keyToResolve, ResolutionList resolutionPath) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.CreateObject(Type type, ResolutionList resolutionPath, RegistrationKey keyToResolve) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.TypeRegistration.<>c__DisplayClass3_0.b__1() [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.RegistrationWithStrategy.ExecuteWithLock(Object lockObject, Func1 getter, Func
1 factory, ResolutionList resolutionPath) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.TypeRegistration.ResolvePerContext(ObjectContainer container, RegistrationKey keyToResolve, ResolutionList resolutionPath) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.RegistrationWithStrategy.Resolve(ObjectContainer container, RegistrationKey keyToResolve, ResolutionList resolutionPath) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.ResolveObject(RegistrationKey keyToResolve, ResolutionList resolutionPath) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.Resolve(Type typeToResolve, ResolutionList resolutionPath, String name) [xUnit.net 00:00:01.08] at BoDi.ObjectContainer.Resolve(Type typeToResolve, String name) [xUnit.net 00:00:01.08] at TechTalk.SpecFlow.Infrastructure.TestObjectResolver.ResolveBindingInstance(Type bindingType, IObjectContainer container) [xUnit.net 00:00:01.08] at lambda_method(Closure , IContextManager , String , String ) [xUnit.net 00:00:01.08] at TechTalk.SpecFlow.Bindings.BindingInvoker.InvokeBinding(IBinding binding, IContextManager contextManager, Object[] arguments, ITestTracer testTracer, TimeSpan& duration) [xUnit.net 00:00:01.08] at TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.ExecuteStepMatch(BindingMatch match, Object[] arguments, TimeSpan& duration) [xUnit.net 00:00:01.08] at TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.ExecuteStep(IContextManager contextManager, StepInstance stepInstance) [xUnit.net 00:00:01.08] at TechTalk.SpecFlow.Infrastructure.TestExecutionEngine.OnAfterLastStep() [xUnit.net 00:00:01.08] at TechTalk.SpecFlow.TestRunner.CollectScenarioErrors() [xUnit.net 00:00:01.08] at ebs_test_tool.Features.EBSIntegrationTestFeature.ScenarioCleanup() [xUnit.net 00:00:01.08]
I also noticed this in my output:
[xUnit.net 00:00:01.09] Output: [xUnit.net 00:00:01.09] Given MRF application "Eb.MarketFeed.Fx" runs version "0.1.52" [xUnit.net 00:00:01.09] -> error: Interface cannot be resolved: Microsoft.Extensions.Logging.ILogger`1[NX.Data.Client, DpNet.Data, Version=0.0.2.178, Culture=neutral, PublicKeyToken=null]] (resolution path: eb_test_tool.Steps.IntegrationTestStepDefinitions) (0.0s)
Previously when I got a similar error I had to add [Binding]
to my class but I already have it.
I'm wondering if this is indeed a binding issue or if it's just that I'm trying to pass ILogger<Client>
is a class that isn't Client
. How do I resolve this?
Solution 1:[1]
You will need to register an ILogger<Client>
object in the SpecFlow IoC container. This should be done in a "BeforeScenario" hook:
[Binding]
public class SpecFlowHooks
{
public SpecFlowHooks(IObjectContainer container)
{
this.container = container;
}
[BeforeScenario]
public void CreateLogger()
{
ILogger<Client> logger = // initialize client logger here
container.RegisterInstanceAs(logger);
}
}
If you do not do this, the IoC container that initializes new instances of your step definitions will not know how to resolve the ILogger<Client>
interface, which results in the exception you reported.
Solution 2:[2]
To add more clarifiaction to Greg Burghardt's answer, you can write a static class that would help you get the instance of the logger with a specific type
[Binding]
public class SpecFlowHooks
{
private readonly IObjectContainer _container;
public SpecFlowHooks(IObjectContainer container)
{
_container = container;
}
[BeforeScenario]
public void CreateLogger()
{
var logger = LoggerDriver.GetLogger<Client>();
_container.RegisterInstanceAs(logger);
}
}
public static class LoggerDriver
{
public static ILogger<T> GetLogger<T>() where T : class
{
ILogger<T> logger = new LoggerFactory().CreateLogger<T>();
return logger;
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Greg Burghardt |
Solution 2 | Zwelithini.Mphanza |