Search code examples
c#seleniumselenium-webdriverbddspecflow

BoDi.ObjectContainerException Interface cannot be resolved: OpenQA.Selenium.IWebDriver


I am creating a new framework as PageFactory has been deprecated. I am getting the error

BoDi.ObjectContainerException : Interface cannot be resolved: OpenQA.Selenium.IWebDriver (resolution path: UnitTestProject1.Base)
TearDown : BoDi.ObjectContainerException : Interface cannot be resolved: OpenQA.Selenium.IWebDriver (resolution path: UnitTestProject1.Base)

My code snippet of my framework is below. I am not sure how I can resolve this. I am aware I could use Context Injection but am not sure what attributes from my framework I should move and to where. I was thinking should I move the IWedriver Driver to a class and call this in a constructor but not sure where I should call it in the steps file.

Some help to resolve this issue appreciated, thanks.

using System;
using System.Collections.Generic;
using System.Text;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using SeleniumExtras.PageObjects;


namespace UnitTestProject1
{
    public class Base : SpecflowBaseTest
    {
        protected IWebDriver driver { get; set; }

    public Base(IWebDriver Driver)
    {
        driver = Driver;
        //PageFactory.InitElements(Driver, this);
    }
   }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TechTalk.SpecFlow;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using UnitTestProject1.Page;
using OpenQA.Selenium.Remote;
using BoDi;

namespace UnitTestProject1
{
[Binding]
public class SpecflowBaseTest : TechTalk.SpecFlow.Steps
{
    // For additional details on SpecFlow hooks see 
http://go.specflow.org/doc-hooks
    protected IWebDriver Driver { get; set; }
    private readonly IObjectContainer objectContainer;

    [BeforeScenario]
    public void BeforeScenario()
    {
        Driver = new ChromeDriver();
        //this.objectContainer = objectContainer;
        //ObjectContainer.RegisterInstanceAs<IWebDriver>(Driver);
        Driver.Manage().Window.Maximize();
    }

    [AfterScenario]
    public void AfterScenario()
    {
        Driver.Close();
        Driver.Quit();
    }

    public void NavigateToURL(string URL)
    {
        Driver.Navigate().GoToUrl(URL);
    }

    protected LoginPage LoginPage => new LoginPage(Driver);
  }
}

using NUnit.Framework;
using System;
using TechTalk.SpecFlow;


namespace UnitTestProject1.Steps
{
[Binding, Parallelizable]

public class LoginSteps : SpecflowBaseTest
{
    [Given(@"I navigate to (.*)")]
    public void GivenINavigateToHttpsCompany_Com(string URL)
    {
        NavigateToURL(URL);
    }

    [Given(@"I enter bw_(.*) and (.*)")]
    public void GivenIEnterBw_Valid_UserAnd(string Username, string 
Password)
    {
        LoginPage.Login(Username, Password);
    }

    [Then(@"I am logged in as bw_valid_user")]
    public void ThenIAmLoggedInAsBw_Valid_User()
    {
        //LoginPage.
    }
  }
}

Solution

  • You need to initialize a new IWebDriver object and register it with SpecFlow's dependency injection framework in a [BeforeScenario].

    [Binding]
    public class SeleniumSpecFlowHooks
    {
        private readonly IObjectContainer container;
    
        public SeleniumSpecFlowHooks(IObjectContainer container)
        {
            this.container = container;
        }
    
        [BeforeScenario]
        public void CreateWebDriver()
        {
            // Create and configure a concrete instance of IWebDriver
            IWebDriver driver = new FirefoxDriver(...)
            {
                ...
            };
    
            // Make this instance available to all other step definitions
            container.RegisterInstance(driver);
        }
    
        [AfterScenario]
        public void DestroyWebDriver()
        {
            IWebDriver driver = container.Resolve<IWebDriver>();
    
            driver.Close();
            driver.Dispose();
        }
    }
    

    Your step definition classes should not be initializing the web driver. Just declare an IWebDriver argument in their constructors.

    Base class:

    [Binding]
    public class SpecflowBaseTest : TechTalk.SpecFlow.Steps
    {
        protected IWebDriver Driver { get; }
        protected LoginPage LoginPage { get; }
    
        public SpecflowBaseTest(IWebDriver driver)
        {
            Driver = driver;
            LoginPage = new LoginPage(driver);
        }
    
        public void NavigateToURL(string URL)
        {
            Driver.Navigate().GoToUrl(URL);
        }
    }
    

    Child class:

    [Binding, Parallelizable]
    public class LoginSteps : SpecflowBaseTest
    {
        [Given(@"I navigate to (.*)")]
        public void GivenINavigateToHttpsCompany_Com(string URL)
        {
            NavigateToURL(URL);
        }
    
        [Given(@"I enter bw_(.*) and (.*)")]
        public void GivenIEnterBw_Valid_UserAnd(string Username, string Password)
        {
            LoginPage.Login(Username, Password);
        }
    
        [Then(@"I am logged in as bw_valid_user")]
        public void ThenIAmLoggedInAsBw_Valid_User()
        {
            //LoginPage.
        }
    }