I am creating a c# based automated testing framework and have configuration files that link test case methods and class names to requirement IDs. The framework will create a TestPlan that is a list of multiple test cases that will executed one after another.
Since there are thousands of testcases (and more all the time) I want to call these classes and methods by reflection, but I am concerned that these methods will create singleton instances of supporting classes that will hang around after the method returns that won't be reused when the next test method is called by reflection.
My question is: will each call use the same static instance in the assembly? Or will each call create a new instance of the singleton? Without reflection in the mix it is a simple answer, but with it ... I am not certain.
Example: I will call SomePageTestCases.TestcaseMethod1() by reflection below. This creates a static instance of CurrentPage which contains the Page object used by the TestMethod. After the Testcase returns, what happens if I call another TestMethod in another class by reflection? Does the CurrentPage.Instance persist and will it be used by the newly called test method? Or will it original be orphaned in the assembly and a new static instance of CurrentPage be created by the new test methods call?
namespace Framework.TestCases
{
public class SomePageTestCases
{
public bool TestCaseMethod1()
{
return (CurrentPage.Instance.Page as SomePage)?.DoSomething() ?? false;
}
}
}
namespace Framework
{
public class CurrentPage
{
private object TopLevelControl;
private static CurrentPage _instance;
public static CurrentPage Instance => _instance ?? (_instance = new CurrentPage());
private Page _page;
public Page Page
{
get
{
if (_page == null || _page.Name != GetCurrentPageName())
_page = GetCurrentPage();
return _page;
}
}
private CurrentPage()
{
//hooks the top level control of the system under test.
throw new NotImplementedException();
}
private static string GetCurrentPageName()
{
//return the page name of the current page from the TopLevelControl.
throw new NotImplementedException();
}
private static Page GetCurrentPage()
{
//Searches the TopLevelControl for the current PageObject and returns it.
throw new NotImplementedException();
}
}
}
namespace Framework.Base
{
public abstract class Page
{
public string Name { get; private set; }
public object PageObject { get; private set; }
protected void LoadPage(string pageClassName)
{
throw new NotImplementedException();
//Name = something;
//PageObject = something;
}
}
}
namespace Framework.Pages
{
public class SomePage : Page
{
public bool DoSomething()
{
throw new NotImplementedException();
}
public SomePage()
{
LoadPage("SomePage");
}
}
}
Related
What I have is:
public static class IDs {
public static string someID { get; set; }
static IDs() {
log.info(someID);
// use someID here
}
}
public class otherClass {
public void otherMethod(string sym) {
IDs.someID = sym;
}
}
and then using an instance of otherClass like this:
otherClassInstance.otherMethod("someStringSymbol");
I dont have any build errors, but log.info(someID); is printing null.
I was expecting it to be someStringSymbol.
This is because the static constructor is called automatically before the first instance is created or any static members are referenced..
This means that when an instance of otherClass invokes IDs.someID = sym; the first operation that gets executed is the static constructor, i.e. the code inside static IDs().
At this point the static variable has not yet been initialized, and you are basically executing log.info(null);.
After the static constructor completes, the variable is initialized, so you should be able to see its value inside otherMethod, after the first reference of IDs.
Given the OP's requirement:
I want to use the value passed in someID in a switch statement
The solution could be to simply execute a static method whenever a new value is set, with the help of explicit getters and setters:
public static class IDs
{
private static string _someID; // backing field
public static string SomeID
{
get { return _someID; }
set
{
_someID = value;
DoSomethingWithSomeID();
}
}
private static DoSomethingWithSomeID()
{
// Use SomeID here.
switch (IDs.SomeID)
{
...
}
}
}
public class OtherClass
{
public void OtherMethod(string sym)
{
// This will set a new value to the property
// and invoke DoSomethingWithSomeID.
IDs.SomeID = sym;
}
}
DoSomethingWithSomeID will be invoked every time someone sets a new value to SomeID.
I dont think what you are trying to do is suited to static classes. I would try the following
public class IDs{
public string someID{ get; set; }
public IDs(string someId){
this.someID = someId;
log.info(this.someID);
//use someID here
}
}
pulic class otherClass{
public otherMethod(string sym){
IDs id = new IDs(sym);
}
}
public class anotherClass{
//access instance of otherClass in wrp and call otherMethod()
wrp.otherMethod("someStringSymbol")
}
Here is my generic method from which i want to return the class object
public class TestBase
{
public T NavigateandReturntheObject<T>() where T : new()
{
//do navigate to page stuff and return the page object
//previously it was - return new T();
//Now i want to do something like this
return PageObjectBase<T>.PageObject;
}
}
Above method calling the below static generic class which will handle object creation of a particular class
public static class PageObjectBase<T> where T : class, new()
{
private static T singleTonObject;
public static T PageObject
{
get
{
return InstanceCreation();
}
}
public static T InstanceCreation()
{
if (singleTonObject == null)
{
singleTonObject = new T();
}
return singleTonObject;
}
}
How can i call the PageObject property from my test base class please advice.
Note : I have searched forum and find answers relevant to generic method to another generic method calling.The same is achieved by reflection.Can we use reflection in my case too? If so how can we do it.
You can add another constraint 'class' to NavigateandReturntheObject
public T NavigateandReturntheObject<T>() where T : class,new()
Complete Code.
public class TestBase
{
public T NavigateandReturntheObject<T>() where T : class,new()
{
//do navigate to page stuff and return the page object
//previously it was - return new T();
//Now i want to do something like this
return PageObjectBase<T>.PageObject;
}
}
Demo Code
public class TestClass
{
public string Name{get;set;}
public TestClass()
{
Name = "Dummy Name";
}
}
var testBase = new TestBase();
var sample = testBase.NavigateandReturntheObject<TestClass>();
Console.WriteLine(sample.Name);
Output
Dummy Name
I'm using the Singleton design pattern and I must return the object if it hasn't been used before.
I get an exception in the following code :
namespace app.Models
{
public class Conexion:DbContext
{
private static Conexion Instance = null;
private Conexion(string con) : base(con) { }
public static Conexion MainConexion
{
get {//error here
if (Instance == null)
{
Instance = new Conexion(#"Server=*****; User Id=***;Password=****; Database=****");
}
return Instance;
}
}
public DbSet<label> Labels { get; set; }
public DbSet<checke_status> CheckStatus { get; set; }
public void SaveChanges()
{
MainConexion.SaveChanges();
}
}
}
How can I solve this?
Remove the override of the SaveChanges method:
namespace app.Models
{
public class Conexion : DbContext
{
private static Conexion Instance = null;
private Conexion(string con) : base(con) { }
public static Conexion MainConexion
{
get
{ //error here
if (Instance == null)
{
Instance = new Conexion(
#"Server=*****; User Id=***;Password=****; Database=****");
}
return Instance;
}
}
public DbSet<label> Labels { get; set; }
public DbSet<checke_status> CheckStatus { get; set; }
}
}
Since you have a private constructor, the only instance of this class that can be used is the one exposed in the MainConexion property. It looks like you were trying to make sure that when any instance's SaveChanges method was called that the SaveChanges method on the MainConnection property's instance was called. This is not necessary, because you can only ever have one instance of the Conexion class, and it's the instance that you want to call SaveChanges on. The usage is still the same:
Conexion.MainConexion.SaveChanges();
That being said, I think you would have better luck if you were to not implement it this way. It would probably be better to open and close connections as they were needed, rather than rely on a single connection instance. What happens if the connection is interrupted? Rather than getting a single error, your application will be broken.
i have this class to use to get instances of objects from different DLL depending on a string which have the name of dlls.
public class PluginFactory
{
private static volatile PluginFactory Factory;
private static object syncRoot = new Object();
private PluginFactory()
{
}
public static PluginFactory Instance
{
get
{
if (Factory == null)
{
lock (syncRoot)
{
if (Factory == null)
{
Factory = new PluginFactory();
}
}
}
return Factory;
}
}
public IPlugableInterface GetPlugin(string assemblyName)
{
ObjectFactory.Initialize(x => x.AddRegistry(new PluginRegistery(assemblyName)));
_prog = ObjectFactory.GetInstance<PluginProgrammer>();
return _prog.Plugin;
}
PluginProgrammer _prog;
[Pluggable("Default")]
[PluginFamily("Default")]
internal class PluginProgrammer
{
public readonly IPlugableInterface Plugin;
public PluginProgrammer(IPlugableInterface Plugin)
{
this.Plugin = Plugin;
}
}
internal class PluginRegistery : Registry
{
public PluginRegistery(string assembly)
{
Scan(
scanner =>
{
scanner.AssembliesFromApplicationBaseDirectory(x => x.ManifestModule.Name == assembly);
scanner.AddAllTypesOf<IPlugableInterface>();
});
}
}
}
This works fine for the first call , it inject to the DLL which has its name as assembly-name and return an object of it, the second time i call it with a different assemblyname it doesnt work and doesnt return an object , the funny thing is it never pass this line if i debug and if i run it without breakpoint nothing just happen!.
_prog = ObjectFactory.GetInstance<PluginProgrammer>();
any idea why this is happening ? any idea how can i fix this or redesign it to accomplish what i want ?
I think you should be using named instances as you want to have different registrations in different DLLs. You could use the dllname as the name of the instance for example.
See also: http://geekswithblogs.net/michelotti/archive/2009/10/14/structuremap-with-named-instance-and-with-method.aspx
I'm calling my custom factory that I created (PhotoServiceFactory), which is a singleton that allows me to get at a specific custom service type back (in this case FacebookService). FacebookService is also a singleton. In FacebookService I've exposed an instance of FacebookAlbumPhoto through a property. I did this because then I don't have to have a ton of the same code over and over again creating a new instance of FacebookAlbumPhoto...I can get an instance using the FacebookService's property.
PhotoServiceFactory service = PhotoServiceFactory.CurrentPhotoServiceFactory;
FacebookService facebookService = (FacebookService)service.GetAPIService(APIType.Facebook);
FacebookAlbumPhoto facebookPhoto = facebookService.FacebookAlbumPhoto.GetFacebookAlbumPhoto(selectedPhotoID);
So this is all set up now, I created all this and just testing it now.
What's happening is my code is bombing out at this line:
FacebookAlbumPhoto facebookPhoto = facebookService.FacebookAlbumPhoto.GetFacebookAlbumPhoto(selectedPhotoID);
The error I get is when I try to reference the facebookService.FacebookAlbumPhoto instance:
CurrentSession = '_singletonInstance.CurrentSession' threw an exception of type 'System.Threading.ThreadAbortException'
So I don't know if it's because the service singleton is on one thread and then it tries to reference another singleton that's on a completely different thread and that's just not possible? That it's not possible to nest singletons like this? Or could this be another issue altogether? Cause I can't see it.
Here's my ServiceFactory:
public class PhotoServiceFactory
{
private static PhotoServiceFactory _singletonInstance;
private PhotoServiceFactory(){}
public static PhotoServiceFactory CurrentPhotoServiceFactory
{
get
{
_singletonInstance = _singletonInstance ?? (_singletonInstance = new PhotoServiceFactory());
return _singletonInstance;
}
}
public object GetAPIService(APIType apiType)
{
object apiService = null;
switch (apiType)
{
case APIType.Facebook:
apiService = FacebookService.CurrentService;
break;
// rest of code
}
return apiService;
}
So the main singleton here Service has a property to get its related Session:
Here's the FacebookServiceClass:
public class FacebookService
{
private static FacebookService _singletonInstance;
private FacebookService(){}
public FacebookSession CurrentSession
{
get
{
return FacebookSession.GetCurrentSession();
}
}
/// <summary>
/// Gets the current facebook service singleton instance.
/// </summary>
/// <value>The current facebook service.</value>
public static FacebookService CurrentService
{
get
{
_singletonInstance = _singletonInstance ?? (_singletonInstance = new FacebookService());
return _singletonInstance;
}
}
public FacebookAlbumPhoto FacebookAlbumPhoto
{
get
{
return new FacebookAlbumPhoto(); // create an instance automatically so we can start working with this object
}
}
}
Here's the session class:
public class FacebookSession
{
const string loginCallbackUrl = "http://localhost/PhotoUpload/FacebookOauth.aspx";
private FacebookSession()
{
}
public string UserID { get; private set; }
public static FacebookSession GetCurrentSession()
{
//....bunch of other logic is here
FacebookSession facebookSession = CreateNewSession();
return facebookSession;
}
public FacebookSession CreateNewSession()
{
//...some code here
FacebookSession newFacebookSession = new FacebookSession
//... rest of code...
return newFacebookSession;
}
// ... rest of code
}
UPDATED:
As requested here's my FacebookAlbumPhoto class that I created:
public class FacebookAlbumPhoto : FacebookPhotoBase
{
private FacebookSession currentSession;
public FacebookAlbumPhoto()
{
currentSession = FacebookService.CurrentService.CurrentSession;
}
#region Methods
public FacebookAlbumPhoto GetFacebookAlbumPhoto(string photoID)
{
...more code
FacebookPhotoRequest request = new FacebookPhotoRequest(currentSession.UserID, photoID);
...more code
FacebookAlbumPhoto facebookPhoto = ParseFacebookPhoto(json);
return facebookPhoto;
}
...rest of code
}
Two things. First, remember to read over Skeet's catalogue of singleton implementations.
Second, try breaking your code just before the spot where the exception occurs, and then bring up your "Exception" dialogue (ctrl-alt-e). Click the "throw" checkbox next to the CLR (second row of dialogue) and hit ok. Continue debugging your code. The results may tell you where the real problem is.
Don't forgot to go back to the Exception dialogue and remove that check from the check box, after you are done. :)
separate instance creation from initialization