Instantiating a class the parameter passed to it's constructor shows A field initializer cannot reference the non static field - selenium

I have started creating a framework in Selenium Webdriver in C#. I have a base class and a HomePage class. HomePage inherits the base class.
When I instantiate the HomePage class I am getting the error:
A field initializer cannot reference the non static field, method or property autobot_automation.Base.BasePageDriver.get
I have declared the driver variable in the base class and initialised it in the constructor. I do not know why the compiler is showing the error.
My Base Class is:
using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;
using autobot_automation.Pages.HomePage;
using autobot_automation.Pages.Base;
namespace autobot_automation.Base
{
public class BasePage
{
public IWebDriver Driver { get; set; }
public BasePage(IWebDriver driver)
{
Driver = driver;
PageFactory.InitElements(Driver, this);
}
public void GoToURL(string url)
{
Driver.Navigate().GoToUrl(url);
}
#region Page Objects
public HomePage homepage = new HomePage(Driver);
#endregion
}
}
My HomePage Class is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;
using autobot_automation.Pages;
using autobot_automation.Base;
namespace autobot_automation.Pages.HomePage
{
public class HomePage : BasePage
{
//private IWebDriver Driver { get; set; }
public HomePage(IWebDriver driver) : base(driver)
{
//Driver = driver;
//PageFactory.InitElements(Driver, this);
}
}
}
Suggestions please to help me resolve this.
Thanks

The line public HomePage homepage = new HomePage(Driver); in BasePage will be executed before the constructor. It will create new HomePage object with the driver (null at this point) which in turn initialize the Driver property with null.
I suggest you create some kind of support class which will hold the HomePage instance instead of BasePage.
If you insist on keeping it there (not a good design IMHO) creat a constructor which will receive a HomePage object as parameter.

Related

BeforeScenario and AfterScenario hooks not working in specflow

I have the following code in my SeleniumSteps.cs code
I am trying to get the AfterScenario to fire on debugging these tests
using PrivateDomain;
using Machine.Specifications;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using TechTalk.SpecFlow;
namespace Functional.Steps
{
public class SeleniumSteps : PrivateDomain.Steps.SeleniumSteps
{
#region Hooks
[BeforeScenario]
public void Before()
{
// before
}
[AfterTestRun, Scope(Tag = null)]
public new static void AfterTestRun()
{
// after testrun
}
[AfterScenario]
public void AfterScenarioErrorScreenshot()
{
// after scenario
}
#endregion
}
}
using OpenQA.Selenium;
using TechTalk.SpecFlow;
namespace PrivateDomain.Steps
{
[Binding]
[Scope(Tag = "Selenium")]
public class SeleniumSteps
{
protected static IWebDriver webDriver;
public SeleniumSteps();
public virtual IWebDriver WebDriver { get; }
[AfterTestRun]
[Scope(Tag = null)]
public static void AfterTestRun();
[AfterScenarioAttribute(new[] { })]
public virtual void AfterScenario();
}
}
My feature file looks like this:
(Details removed)
#Customer_Portal
Feature: Account Management - Registration
In order to create an account
As a customer
I want to register my details with the application
Scenario: Register
# Registration Form
When I navigate to "/Customer/Account/Register"
// more code...
Scenario: Required Fields
// more code...
Scenario: Invalid Contact Details
// more code...
Scenario: Insufficient Password Strength
// more code...
Scenario: Password Mismatch
// more code...
Scenario: Already Registered
// more code...
Scenario: Invalid Activation
// more code...
Scenario: Already Activated
// more code...
When I debug a test, I can see the debugger hitting the AfterTestRun portion.
However, neither the BeforeScenario or the AfterScenario are being exercised.
Can someone tell me what I'm doing wrong?
First, as Sandesh noted in his answer, you are missing [Binding] attribute for your SeleniumSteps subclass. It's not enough to have [Binding] only in base class, you must apply it to every class where are your hook methods or step definitions (bindings), because that is the way how specflow is searching for hooks and bindings under the hood. It is like scope identifier. If you miss to place [Binding] attribute to class, specflow will not search for potential hook methods or bindings in that class. Link on documentation: https://specflow.org/documentation/Hooks/
This link can be useful also. Check answer given by RunOfTheShipe: Specflow test step inheritance causes "Ambiguous step definitions"
You have missed [Binding] attribute in your SeleniumSteps
namespace Functional.Steps
{
[Binding]
public class SeleniumSteps : PrivateDomain.Steps.SeleniumSteps
{
#region Hooks
[BeforeScenario]
public void Before()
{
// before
}
}
}

structuremap configuration asp.net mvc 4

I have a problem with MVC4 StructureMap configuration, when I run the project the compiler fires this error
No Default Instance defined for PluginFamily Mace_CrmSystem.Controllers.HomeController
this is my code
global.aspx code
namespace Mace_CrmSystem
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteTable.Routes.MapRoute("Oqla", "Oqla", new { controller = "Home", action = "index" });
RouteConfig.RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new MyCustomeFactory());
ObjectFactory.Initialize(x => x.For<string>().Use<string>());
}
}
}
MycustomeFactory class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using StructureMap;
namespace Mace_CrmSystem
{
public class MyCustomeFactory : System.Web.Mvc.DefaultControllerFactory
{
protected override System.Web.Mvc.IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
{
return StructureMap.ObjectFactory.GetInstance(controllerType) as System.Web.Mvc.IController;
}
}
}
Controller class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace Mace_CrmSystem.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public HomeController(string parameter)
{
TempData["Hi"] = "Hi";
}
public ActionResult Index()
{
return View();
}
}
public class logger
{
public void log()
{
}
}
}
what I noticed that when I add a parameter of type object like
public HomeController(logger parameter)
instead of
public HomeController(string parameter)
and
ObjectFactory.Initialize(x => x.For<logger>().Use<logger>());
instead of
ObjectFactory.Initialize(x => x.For<string>().Use<string>());
it works probably but with the string parameter it does not work .
so please couold anyone explain that for me.
From my understanding of StructureMap (and someone please correct me if I'm wrong) the reason you're seeing the behaviour that you're seeing is because StructureMap will use the longest constructor by default and attempt to fill in the parameters with the default instance registered with StructureMap.
In your instance you're not providing a default instance of string so StructureMap doesn't know how to resolve it.
If you wish to do what you're trying to do then your best bet is to look at creating a custom convention (see this answer for more information), however these do rely on knowing the name of the property your constructor is expecting.
Generally though, when dealing with strings your best bet is to move the string to an intermediate type and inject that instead.

How to get the current remote webdriver instance inside onTestFailure(ITestResult)

I want to integrate the code to take screenshot using remoteWebdriver inside, testng's onTestFailure(ITestResult). I am unable to get the current webdriver instance inside onTestFailure().
Okay, I had a similar problem.
And since there's no clear answer here, I would post my ( working) solution
On your BaseTest / TestBase class, make your RemoteWebdriver instance accessible ( either by having it as a public property or with a getter)
In the Listener class (In my case its a public property):
public class BaseTest {
public RemoteWebDriver remoteDriver;
//... initalize driver
}
public class TestListener implements ITestListener {
#Override
public void onTestFailure(ITestResult result) {
BaseTest test = (BaseTest) result.getInstance();
if (test == null) {
return;
}
RemoteWebDriver driver = test.remoteDriver;
}
}

Ninject: How to resolve collection from object type

Just wanted to know if there is a way bind a type and resolve a collection. I dont know if Ninject can do this out of the box. I'm using MVC4 with Ninject3 so I have the NinjectWebCommon.cs where I register the services. There is nowhere I can get the kernel (I read that it was bad practice to access the kernel from elsewhere, but that can certainly be the solution to this).
For example, I'm having this class:
public class CacheManager
{
public IEnumerable<SelectListItem> Get<T>() where T : INameValue
I want to be able to send
CacheManager.Get<City>
and obtain the CityRepository class.
Is it this you want to do? :
using System.Collections.Generic;
using System.Linq;
using Ninject;
using Ninject.Modules;
using Ninject.Syntax;
public class Temp
{
public interface ICity { }
public class SelectListItem
{
}
public class FooCity : SelectListItem, ICity { }
public class BarCity : SelectListItem, ICity {}
public class CityModule : NinjectModule
{
public override void Load()
{
this.Bind<ICity>().To<FooCity>();
this.Bind<ICity>().To<BarCity>();
}
}
public class CacheManager
{
private readonly IResolutionRoot resolutionRoot;
public CacheManager(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public IEnumerable<SelectListItem> Get<T>()
{
return this.resolutionRoot.GetAll<T>().OfType<SelectListItem>();
}
}
}
I'm unclear as to whether you have multiple implementations of T (ICity) or one implementation but several instances (like retrieving a list of city names from the database and creating one instance per name). The later you could solve by a this.Bind>().ToProvider(...) binding.
I ended up doing:
In NinjectWebCommon.cs:
kernel.Bind(typeof(CacheManager))
.ToSelf()
.InSingletonScope();
kernel.Bind<IDataListRepository<Locale>>()
.To<LocaleRepository>();
In CacheManager.cs:
public class CacheManager: IDisposable
{
private IKernel kernel;
public CacheManager(IKernel kernel)
{
this.kernel = kernel;
}
public IEnumerable<T> GetAsEnumerable<T>()
{
var rep = kernel.Get<IDataListRepository<T>>();
return rep.GetAll();
}
I don't know if this is bad-practice (since kernel in theory should only be used in the initialization phase), but I didn't find any other way to do it.
If better options exist, please let me know.

NinjectModule and IProvider not resolving types

Here is the set up that is not working
Using Ninject V3.0
public class LoggerModule : NinjectModule{
public override void Load()
{
Bind<ILogger>.ToProvider(MyLoggerProvider);
}
}
public class MyLoggerProvider: IProvider<ILogger>
{
public object Create(IContext context){
return new OneOfMyLoggers();
}
}
In my application wherever I inject instance of ILogger (using constructor or property injection, just does matter) I never get instance of ILogger resolved.
But If do not use module and/or povider, and bind when kernel is created, everything works like a charm. The following works
public class MyDiResolver()
{
public MyDiResolver()
{
MyKernel = new StandardKernel();
MyKernel.Bind<ILogger>().To<OneOfMyLoggers>();
}
}
The same arrangement of modules and providers works fine in Ninject2.x version. Is there something different about Ninject V3.0 that I am missing?
Thanks
Try passing the module into the StandardKernel so it knows to use it:
using (IKernel kernel = new StandardKernel(new LoggerModule()))
{
ILogger logger = kernel.Get<OneOfMyLoggers>();
}