I was following the example (Aggressive old mode) given in:
http://docs.castleproject.org/Default.aspx?Page=Startable-Facility&NS=Windsor&AspxAutoDetectCookieSupport=1
Here is my full source code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Castle.Facilities.Startable;
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
namespace Test
{
public interface IStartable
{
void Start();
void Stop();
}
public class Startable : IStartable
{
public Startable()
{
Console.WriteLine("Created!");
}
public void Start()
{
Console.WriteLine("Started!");
}
public void Stop()
{
Console.WriteLine("Stopped!");
}
}
[TestFixture]
public class StartableFacilityContainerTest
{
[Test]
public void TestOperation()
{
IKernel container = new DefaultKernel();
container.AddFacility<StartableFacility>();
container.Register(Component.For<Startable>());
Console.WriteLine("Registered!");
container.Dispose();
Console.WriteLine("Released!");
}
}
}
However when I run it, I get:
Registered!
Released!
when I expect to get (as given in the example):
Created!
Started!
Registered!
Stopped!
Released!
Basically my Startable did not start.
This is tested in .Net 4.0 and Castle Windsor 3.0
What did I do wrong?
I'm using Installers. This helped me:
container.AddFacility<StartableFacility>(f => f.DeferredTryStart());
try
container.Register(Component.For<Startable>()
.StartUsingMethod(s => s.Start)
.StopUsingMethod(s => s.Stop);
The problem is you have created and implemented your own IStartable interface instead of just implementing the Castle.Core.IStartable
Related
I try to unit-test a Gui application code that uses
Application.Current.Dispatcher.Invoke() and would like to use the solution provided by #informatorius in the similar thread Using the WPF Dispatcher in unit tests. The code is listed below.
The problem I have is that Application is not resolved, even if I add using System.Windows. Is there some special mechanism to resolve
Application from within a class library that defines the testcases ?
I have the MSTest.TestFramework and MSTest.TestAdapter packages installed.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class ApplicationInitializer
{
[AssemblyInitialize]
public static void AssemblyInitialize(TestContext context)
{
var waitForApplicationRun = new TaskCompletionSource<bool>();
Task.Run(() =>
{
var application = new Application();
application.Startup += (s, e) => { waitForApplicationRun.SetResult(true); };
application.Run();
});
waitForApplicationRun.Task.Wait();
}
[AssemblyCleanup]
public static void AssemblyCleanup()
{
Application.Current.Dispatcher.Invoke(Application.Current.Shutdown);
}
}
[TestClass]
public class MyTestClass
{
[TestMethod]
public void MyTestMethod()
{
// implementation can access Application.Current.Dispatcher
}
}
Answer pointed me into the right direction:
using System.Windows is not enough, I also needed to add reference to PresentationFramework to the project. Dont really understand the auto magic behind that.
I created a new Xamarin.Forms project and I'm having issues with the view model initializing. Nothing happens. I'm using the samples from the Features. I modified the sample code to the following:
public FormsApp(SimpleContainer container)
{
//...
DisplayRootView<ConductorView>();
}
This works as expected, but on my project it simply does not work.
I am using .NET Standard 1.5 (not sure if this is causing the issue). In any case here is my code
App.cs:
using System;
using Caliburn.Micro;
using Caliburn.Micro.Xamarin.Forms;
using UniversalSqlManager.ViewModels;
using Xamarin.Forms;
using INavigationService = Caliburn.Micro.Xamarin.Forms.INavigationService;
using UniversalSqlManager.Views;
namespace UniversalSqlManager
{
public class App : FormsApplication
{
private readonly SimpleContainer container;
public App(SimpleContainer container)
{
this.container = container;
container
.PerRequest<ShellViewModel>();
this.DisplayRootView<ShellView>();
}
protected override void PrepareViewFirst(NavigationPage navigationPage)
{
container.Instance<INavigationService>(new NavigationPageAdapter(navigationPage));
}
}
}
ShellView.xaml:
<?xml version="1.0" encoding="utf-8"?>
<TabbedPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:UniversalSqlManager"
x:Class="UniversalSqlManager.Views.ShellView"
xmlns:cm="clr-namespace:Caliburn.Micro.Xamarin.Forms;assembly=Caliburn.Micro.Platform.Xamarin.Forms"
ItemsSource="{Binding Items}"
SelectedItem="{Binding ActiveItem, Mode=TwoWay}"
Title="Universal SQL Manager">
<TabbedPage.ItemTemplate>
<DataTemplate>
<ContentPage Title="{Binding DisplayName}" cm:View.Model="{Binding}" />
</DataTemplate>
</TabbedPage.ItemTemplate>
</TabbedPage>
ShellView.xaml.cs:
using Xamarin.Forms;
namespace UniversalSqlManager.Views
{
public partial class ShellView
{
public ShellView()
{
InitializeComponent();
}
}
}
ShellViewModel.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using Caliburn.Micro;
using Caliburn.Micro.Xamarin.Forms;
using UniversalSqlManager.ViewModels.Interfaces;
namespace UniversalSqlManager.ViewModels
{
public class ShellViewModel : Conductor<ITabItem>.Collection.OneActive
{
protected override void OnInitialize()
{
//both view models implement ITabItem (which has no methods) and inherit form Screen
Items.Add(new ServersViewModel());
Items.Add(new SettingsViewModel());
ActivateItem(Items[0]);
}
}
}
I'll show iOS as that's the first platform I'm testing on
AppDelegate.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using Caliburn.Micro;
using Foundation;
using UIKit;
namespace UniversalSqlManager.iOS
{
[Register(nameof(AppDelegate))]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
private readonly CaliburnAppDelegate appDelegate = new CaliburnAppDelegate();
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(IoC.Get<App>());
return base.FinishedLaunching(app, options);
}
}
}
CaliburnAppdelegate.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Caliburn.Micro;
using UniversalSqlManager.ViewModels.Interfaces;
namespace UniversalSqlManager.iOS
{
public class CaliburnAppDelegate : CaliburnApplicationDelegate
{
private SimpleContainer container;
public CaliburnAppDelegate()
{
Initialize();
}
protected override void Configure()
{
container = new SimpleContainer();
container.Instance(container);
container.Singleton<App>();
container.Singleton<IEventAggregator, EventAggregator>();
}
protected override void BuildUp(object instance)
{
container.BuildUp(instance);
}
protected override IEnumerable<object> GetAllInstances(Type service)
{
return container.GetAllInstances(service);
}
protected override object GetInstance(Type service, string key)
{
return container.GetInstance(service, key);
}
}
}
So when I run this the ShellView UI shows up, but the ShellViewModel does not get initialized and I get no tabs. Even if I switch to SettingsView or ServersView, the corresponding view models never get initialized. What am I doing wrong? This is my first time with Caliburn Micro on Xamarin.Forms. I've used WPF in the past without issues. Just the documentation is confusing, because it just seems like we have these examples to go by and some blogs that aren't as detailed as the WPF documentation. Any help would be appreciated. I can post my csproj and project.json if that will help too, but I'm hesitant to switch the project type as it was a pain to set that up. I guess another alternative would be to create a new project with a PCL and see if that works? Running out of ideas. Any help is appreciated!
So it turns out the problem was that I was not telling the framework which assemblies to use. The Features samples don't use libraries for the share code. So I added this to CaliburnAppDelegate.cs and to Application.cs to iOS and Android respectively:
protected override IEnumerable<Assembly> SelectAssemblies()
{
return this.GetAssemblies();
}
This is an extension I created in my class library:
public static class Bootstrapper
{
//...
public static IEnumerable<Assembly> GetAssemblies(this object o)
{
IEnumerable<Assembly> assemblies =
new[]
{
o.GetType().GetTypeInfo().Assembly,
typeof(ShellViewModel).GetTypeInfo().Assembly
};
return assemblies;
}
//...
}
and this solves the problem. I hope this help someone else who is having issues hooking up the sample using a class library. By the way I figured this out when comparing with the setup samples.
I wish for structuremap to scan my assemblies and register classes as singletons.
I'd further restrict this to factories, services etc.
For now, however, the challenge is to mark the found registrations as singletons.
I've found out that one way is through conventions.
I've found an example that marks a single, specific registration as singleton, but I want to do it for all registrations.
The example code does not compile; first of all because the IsConcrete etc is not available.
Does anyone have a way forward?
using StructureMap;
using StructureMap.Configuration.DSL;
using StructureMap.Graph;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace planner_gui
{
public class SingletonConvention : IRegistrationConvention
{
public void Process(Type t, Registry registry)
{
if (!(t.IsConcrete()) || !(t.CanBeCreated()) ) return;
registry.For( ... ).Singleton().Use(t);
}
}
public class GuiRegistry : Registry
{
public GuiRegistry()
{
Scan(x =>
{
x.AssemblyContainingType<IExecutionContext>();
x.With(new SingletonConvention());
});
}
}
}
IsConcrete() method is an extension method in StructureMap.TypeRules namespace so adding
using StructureMap.TypeRules
would do the trick.
.......So, I have the below class which I have created as part of my automated test pack, but I am getting an error against the 'ListPostsPage.GoTo(PostType.Page)' line of code, advising that: 'the name PostType does not exist in the current context'. The code for this class is below:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WordpressTests
{
[TestClass]
public class PageTests
{
[TestInitialize]
public void Init()
{
Driver.Initialise();
}
[TestMethod]
public void CanEditAPage()
{
LoginPage.GoTo();
LoginPage.LoginAs("XXXXXX").WithPassword("XXXXXX").Login();
**ListPostsPage.GoTo(PostType.Page);**
ListPostsPage.SelectPost("Sample Page");
Assert.IsTrue(NewPostPage.IsInEditMode(), "Wasn't in edit mode");
Assert.AreEqual("Sample Page", NewPostPage.Title, "Title did not match");
}
[TestCleanup]
public void Cleanup()
{
Driver.Close();
}
}
}
Just for reference, the code for the ListPostsPage class is as follows:
using OpenQA.Selenium;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WordpressTests
{
public class ListPostsPage
{
public static void GoTo(PostType postType)
{
switch (postType)
{
case PostType.Page:
Driver.Instance.FindElement(By.Id("menu-pages")).Click();
Driver.Instance.FindElement(By.LinkText("All Pages")).Click();
break;
}
}
public static void SelectPost(string title)
{
var postLink = Driver.Instance.FindElement(By.LinkText("Sample Page"));
postLink.Click();
}
public enum PostType
{
Page
}
}
}
Does anyone have any ideas as to what the issue may be? Please bear in mind I am fairly new to this, so please be nice! :-)
Any help would be much appreciated.
Cheers
Andy
PostType is an enum member of ListPostsPage but you're trying to access it as if it were a static class.
You should do this:
ListPostsPage.GoTo(ListPostsPage.PostType.Page);
As to total MEF newbie, I'm having a problem with my first test of MEF. My problem code is below-
using System;
using GlobalInterfaces;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace GlobalInterfacesUnitTest
{
[TestClass]
public class GlobalInterfacesUnitTest
{
[TestMethod]
public void TestMethod1()
{
[ImportMany(AllowRecomposition = true)]
Lazy<IComponentGui, IImportComponentGuiCapabilites>[] Senders {get;set;}
}
}
}
The problem that I cannot get the compiler to find "ImportMany" attribute. I've checked the references against several demos and copied their references and still have the same problem. I cannot see what I'm overlooking. I am using VS2010 / Net4.0.
You can't define properties inside method. Move it out to class. Try:
[TestClass]
public class GlobalInterfacesUnitTest
{
[ImportMany(AllowRecomposition = true)]
Lazy<IComponentGui, IImportComponentGuiCapabilites>[] Senders {get;set;}
[TestMethod]
public void TestMethod1()
{
}
}