Error when using a custom view location convention with Nancy's ConfigurableBootstrapper - nancy

I am using a subclass of ConfigurableBootstrapper to test my Nancy modules. This is a workaround to get the ConfigurableBootstrapper to pick up the custom view location convention I use in the 'real' bootstrapper:
public class ConfigurableBootstrapperWithCustomConvention : ConfigurableBootstrapper
{
public ConfigurableBootstrapperWithCustomConvention(Action<ConfigurableBootstrapperConfigurator> configuration)
: base(configuration)
{
}
protected override void ConfigureConventions(NancyConventions nancyConventions)
{
nancyConventions.ViewLocationConventions.Add((viewName, model, context) =>
string.Concat(context.ModuleName, "/Views/", viewName));
base.ConfigureConventions(nancyConventions);
}
}
In my tests I first set the root path to that of my nancy project using the FakeRootPathProvider. This contains the necessary folder structure ("/Home/Views/Index.cshtml") for the view used in HomeModule to be located using this custom convention. The (simplified) test code:
[Test]
public void when_the_default_page_is_loaded_it_should_show_links_to_submit_form()
{
FakeRootPathProvider.RootPath = "../../../MyApp.Web";
var bootstrapper = new ConfigurableBootstrapperWithCustomConvention(with =>
{
with.RootPathProvider(new FakeRootPathProvider());
with.ViewEngine<RazorViewEngine>();
with.Module<HomeModule>();
});
var browser = new Browser(bootstrapper);
var response = browser.Get("/");
Assert.That(response.Body.AsString(), Is.StringContaining("<a href=\"SubmitSelf\">"));
}
When I run this test I get the following exception (at the call to response.Body):
System.ArgumentNullException : Value cannot be null.
Parameter name: httpContext
at System.Web.HttpContextWrapper..ctor(HttpContext httpContext)
at System.Web.Optimization.Styles.RenderFormat(String tagFormat, String[] paths)
at RazorOutput.RazorView.Execute()
at Nancy.ViewEngines.Razor.NancyRazorViewBase`1.ExecuteView(String body, IDictionary`2 sectionContents)
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid3<T0,T1,T2>(CallSite site, T0 arg0, T1 arg1, T2 arg2)
at Nancy.ViewEngines.Razor.RazorViewEngine.<>c__DisplayClass27.<RenderView>b__26(Stream stream)
at Nancy.Testing.BrowserResponse.get_Body()
at MyApp.Tests.Integration.Web.Home.HomeModuleTests.when_the_default_page_is_loaded_it_should_show_links_to_submit_form() in HomeModuleTests.cs: line 44
If I set the Fake root path to be "../../../MyApp.Web/Home/Views" instead, the test runs OK. (It appears that the custom view location convention is being ignored when testing using Nancy's "Browser" class).
Is there some issue with setting a NancyConvention in this way?
If so is there a different way to set a view location convention with ConfigurableBootstrapper?

Related

How to mock Prisms IContainerRegistry

Prism.Ninject 7.1.0.431
Prism 7.1.0.431
NUnit 3.3.3
NSubstitute
Previously using Prism 6.3 we had a set of unit test to confirm that we had all of our bindings in place as follows
protected IKernel TestKernel;
[SetUp]
public void Given
{
TestKernel = new StandardKernel();
SUT = new MyModule( TestKernel );
Core = Assembly.Load( "MyDLL.Core" ).GetTypes();
Common = Assembly.Load( "MyDLL.Common" ).GetTypes();
SUT.Initialize();
}
[ Test ]
public void Then_ViewModels_Will_Be_Bound()
{
var testCollection = Common
.Where( item => item.IsPublic )
.Where( item => item.Name.EndsWith( "ViewModel" ) );
foreach ( var item in testCollection )
{
Assert.That( TestKernel.GetBindings( item ).Any, $"Test Failed: {item.Name}" );
}
}
However in Ninject 7.1, the IModule interface has changed somewhat, so now parts are registered differently in
public void RegisterTypes(
IContainerRegistry containerRegistry )
I'm just trying to get my unit tests up and running again with this new IModule format. I had tried changing my given to be as follows
protected override void Given()
{
TestKernel = new StandardKernel();
TestContainerRegistry = Substitute.For<IContainerRegistry>();
TestContainerRegistry.GetContainer().Returns( TestKernel );
SUT = new MyModule();
}
However I get the following when I attempt to run my tests.
System.InvalidCastException : Unable to cast object of type 'Castle.Proxies.IContainerRegistryProxy' to type 'Prism.Ioc.IContainerExtension`1[Ninject.IKernel]'.
If anyone has any idea how I might be able to mock this it would be appreciated, as I'm currently at an impasse.
How you should test is always a hot topic full of disagreement, so I will try to give you some general information here. Prism.Ninject implements the container abstractions with the Prism.Ninject.Ioc.NinjectContainerExtension. This has two constructors, a default and one that allows you to pass in a specific Kernel.
Prism also implements extension methods for each of the containers to pull the container from the abstraction. You can achieve this in a couple of ways:
containerRegistry.GetContainer().SomeContainerSpecificApi()
Alternatively you could do:
var app = new MyApp();
app.Container.GetContainer().SomeContainerSpecificApi();
Again there are a variety of ways that you could implement your tests and I'm not about to get into how you should test. I will however say that in the event you don't want to create an app and you're just looking to validate that your types are registered for a Prism Module you might try something like:
var containerExtension = new NinjectContainerExtension();
var module = new MyModule();
module.RegisterTypes(containerExtension);
Assert.IsTrue(containerExtension.Instance.IsRegistered<MyType>());
I think I've figured it out (or made progress at least)
Instead of substituting with IContainerRegistry I had to use the following
protected override void Given()
{
TestKernel = new StandardKernel();
TestContainerRegistry = Substitute.For<IContainerExtension<IKernel>>();
TestContainerRegistry.GetContainer().Returns( TestKernel );
SUT = new MyModule();
}
Although it looks like I'm going to have to make more substitutes etc in order to have the containerRegistry.Register (etc) wind up in my TestKernel for verification.

Ninject does not resolve dependency correctly in silverlight project

I have a silverlight 4 project with mvvmlight and ninject 3.x.
I've setup the container like this
kernel = new StandardKernel(new ViewModelModule(), new ClientSessionModule());
And the modules like this
public class ViewModelModule : NinjectModule
{
public override void Load()
{
((StandardKernel)Kernel)
.Bind(scanner => scanner.FromThisAssembly()
.Select(x => x.IsSubclassOf(typeof(ViewModelBase)))
.BindDefaultInterface());
}
}
and
public class ClientSessionModule : NinjectModule
{
public override void Load()
{
Kernel.Bind<IClientContext>().To<ClientContext>().InSingletonScope();
}
}
Now the problem is the latter one. At one point in the application this dependency is resolved explictly and updated like this:
var context = App.Ioc.Get<IClientContext>();
context.Username = "just a sample name";
Now when a ViewModel is loaded it get the IClientContext injected like
public MainViewModel(IClientContext clientContext)
The problem is that the instance does not have the name set earlier.
But if I inside the same ViewModel resolves explictly again I get the expected instance with the name set.
What am I missing since the sigleton does not get injected as I expected it to be automatically?
Just found a duplicate kernel in my solution. And that explains why I was not able so resolve as expected as I had 2 kernels running

pass Application as argument in WPF

i have a solution combined with several projects.
this is my App.xaml.cs
public partial class App : Application
{
private SiteManager _siteManager = new SiteManager();
public SiteManager SiteManager
{
get { return _siteManager; }
set { _siteManager = value; }
}
}
during my run i call another project in the same solution
SiteDll.MainWindow siteManagerDialog = new SiteDll.MainWindow();
siteManagerDialog.Show();
but i dont know how to pass all vars in App.xaml.cs to SiteDll.MainWindow siteManagerDialog.
i tried:
SiteDll.MainWindow siteManagerDialog = new SiteDll.MainWindow((App)Application.Current);
siteManagerDialog.Show();
and cast it in SiteDll.MainWindow constructor:
public MainWindow(object me)
{
Application app = ((App)me);
InitializeComponent();
}
but i get casting error...
what is the correct way to do it ?
You are casting YourApplication1.App type to YourApplication2.App which are different types. That's why you get a invalid cast exception.
What you can do is, you can put your common variables in a separate assembly and reference this assembly from both of your applications.
Edit
I would also suggest you to add a 'WPF User Control Library' and then reference it when you are using wpf windows/pages/user controls from other assemblies, to prevent such confusions.

How can I get started with PHPUnit, where my class construct requires a preconfigured db connection?

I have a class that uses a lot of database internally, so I built the constructor with a $db handle that I am supposed to pass to it.
I am just getting started with PHPUnit, and I am not sure how I should go ahead and pass the database handle through setup.
// Test code
public function setUp(/*do I pass a database handle through here, using a reference? aka &$db*/){
$this->_acl = new acl;
}
// Construct from acl class
public function __construct(Zend_Db_Adapter_Abstract $db, $config = array()){
You would do it like this:
public class TestMyACL extends PHPUnit_Framework_TestCase {
protected $adapter;
protected $config;
protected $myACL;
protected function setUp() {
$this->adapter = // however you create a new ZendDbADapter
$this->config = // however you create a new config array
$this->myACL = new ACL($this->adapter, $this->config); // This is the System Under Test (SUT)
}
}
IMHO, you need to work on your naming conventions. See Zend Framework Naming Conventions, for a start. An example would be the underscore, look up variables in the link. Also class naming.
You can do normally without reference same as constructor because this method is simplest.

Silverlight: Cannot use reflection to GetValue of a field across XAPs?

I have a Silverlight application which has two different XAPs - an InitialXAP which is loaded statically by the HTML page and a DynamicXAP which is loaded from code within the initial XAP. The DynamicXAP is loaded with code similar to this:
var asm = LoadAssemblyFromXap(stream, "DLLName");
// LoadAssemblyFromXAP will load the DynamicXAP as a file stream,
// unpack it and load DLLName as a dll.
var controllerType = asm.GetType("ClassNameToInstantiate_InsideAsm");
var constructor = controllerType.GetConstructor(Type.EmptyTypes);
return constructor.Invoke(null);
I have a class which uses reflection (specifically FieldInfo.GetValue) to do data binding. This class is defined in the InitialXAP. If I try to use this class in the DynamicXAP, I get an error:
Message: Unhandled Error in Silverlight Application System.FieldAccessException: Class.In.DynamicXAP.Which.Uses.The.Reflection.Class.In.InitialXAP
at System.Reflection.RtFieldInfo.PerformVisibilityCheckOnField(IntPtr field, Object target, IntPtr declaringType, FieldAttributes attr, UInt32 invocationFlags)
at System.Reflection.RtFieldInfo.InternalGetValue(Object obj, Boolean doVisibilityCheck, Boolean doCheckConsistency)
at System.Reflection.RtFieldInfo.InternalGetValue(Object obj, Boolean doVisibilityCheck)
at System.Reflection.RtFieldInfo.GetValue(Object obj)
I can get around this error by creating a subclass of the class using reflection and overriding the method using reflection like so:
public class InitialXAP.ClassUsingReflection {
public virtual object GetValue()
{
return fieldInfo.GetValue(parent);
}
}
public class ClassUsingReflection : InitialXAP.ClassUsingReflection {
public override object GetValue()
{
return fieldInfo.GetValue(parent);
}
}
But I would prefer to avoid this duplication by allowing reflection from the InitialXAP in the DynamicXAP. Any ideas on what I can do?
Although there is a learning curve, I would look at Silverlight MEF or Prism (both are together at last in the latest Prism 4 Beta). They both support dynamic loading of modules and enforce good patterns for reuse and separate/team development.
InitialXAP.ClassUsingReflection...
Note the duplicate isn't part of the inital xap namespace (ClassUsingReflection), and may be imported.
Notice GetVisible - as in not visible to Dynamic xap...
Just leave the duplicate (take away base class obviously) and try.

Resources