Skip to content

Commit

Permalink
borrow ideas from the chris ortman fork, but keep the same feel as th…
Browse files Browse the repository at this point in the history
…e original framework
  • Loading branch information
gregoryjscott committed Oct 13, 2010
1 parent add6e33 commit e246326
Show file tree
Hide file tree
Showing 23 changed files with 4,672 additions and 136 deletions.
34 changes: 30 additions & 4 deletions MvcIntegrationTestFramework/Browsing/BrowsingSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,43 @@ public BrowsingSession()
Cookies = new HttpCookieCollection();
}

public RequestResult ProcessRequest(string url)
public RequestResult Get(string url)
{
return ProcessRequest(url, HttpVerbs.Get, null);
return ProcessRequest(url, HttpVerbs.Get, new NameValueCollection());
}

public RequestResult ProcessRequest(string url, HttpVerbs httpVerb, NameValueCollection formValues)
/// <summary>
/// Sends a post to your url. Url should NOT start with a /
/// </summary>
/// <param name="url"></param>
/// <param name="formData"></param>
/// <example>
/// <code>
/// var result = Post("registration/create", new
/// {
/// Form = new
/// {
/// InvoiceNumber = "10000",
/// AmountDue = "10.00",
/// Email = "chriso@innovsys.com",
/// Password = "welcome",
/// ConfirmPassword = "welcome"
/// }
/// });
/// </code>
/// </example>
public RequestResult Post(string url, object formData)
{
var formNameValueCollection = NameValueCollectionConversions.ConvertFromObject(formData);
return ProcessRequest(url, HttpVerbs.Post, formNameValueCollection);
}

private RequestResult ProcessRequest(string url, HttpVerbs httpVerb = HttpVerbs.Get, NameValueCollection formValues = null)
{
return ProcessRequest(url, httpVerb, formValues, null);
}

public RequestResult ProcessRequest(string url, HttpVerbs httpVerb, NameValueCollection formValues, NameValueCollection headers)
private RequestResult ProcessRequest(string url, HttpVerbs httpVerb, NameValueCollection formValues, NameValueCollection headers)
{
if (url == null) throw new ArgumentNullException("url");

Expand Down
54 changes: 44 additions & 10 deletions MvcIntegrationTestFramework/Hosting/AppHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,29 @@ namespace MvcIntegrationTestFramework.Hosting
/// </summary>
public class AppHost
{
private readonly AppDomainProxy appDomainProxy; // The gateway to the ASP.NET-enabled .NET appdomain
private readonly AppDomainProxy _appDomainProxy; // The gateway to the ASP.NET-enabled .NET appdomain

public AppHost(string appPhysicalDirectory) : this(appPhysicalDirectory, "/")
{
}

public AppHost(string appPhysicalDirectory, string virtualDirectory)
private AppHost(string appPhysicalDirectory, string virtualDirectory = "/")
{
try {
appDomainProxy = (AppDomainProxy) ApplicationHost.CreateApplicationHost(typeof (AppDomainProxy), virtualDirectory, appPhysicalDirectory);
_appDomainProxy = (AppDomainProxy) ApplicationHost.CreateApplicationHost(typeof (AppDomainProxy), virtualDirectory, appPhysicalDirectory);
} catch(FileNotFoundException ex) {
if((ex.Message != null) && ex.Message.Contains("MvcIntegrationTestFramework"))
throw new InvalidOperationException("Could not load MvcIntegrationTestFramework.dll within a bin directory under " + appPhysicalDirectory + ". Is this the path to your ASP.NET MVC application, and have you set up a post-build event to copy your test assemblies and their dependencies to this folder? See the demo project for an example.");
throw;
}

appDomainProxy.RunCodeInAppDomain(() => {
_appDomainProxy.RunCodeInAppDomain(() => {
InitializeApplication();
AttachTestControllerDescriptorsForAllControllers();
LastRequestData.Reset();
});
}

public void SimulateBrowsingSession(Action<BrowsingSession> testScript)
public void BrowsingSession(Action<BrowsingSession> testScript)
{
var serializableDelegate = new SerializableDelegate<Action<BrowsingSession>>(testScript);
appDomainProxy.RunBrowsingSessionInAppDomain(serializableDelegate);
_appDomainProxy.RunBrowsingSessionInAppDomain(serializableDelegate);
}

#region Initializing app & interceptors
Expand Down Expand Up @@ -107,5 +103,43 @@ private static void RefreshEventsList(HttpApplication appInstance)
}

#endregion

/// <summary>
/// Creates an instance of the AppHost so it can be used to simulate a browsing session.
/// </summary>
/// <param name="pathToYourWebProject">
/// The path to your web project. This is optional if you don't
/// specify we try to guess that it is in the first directory like
/// ../../../*/web.config
/// </param>
/// <returns></returns>
public static AppHost Simulate(string pathToYourWebProject = null)
{
if (pathToYourWebProject == null)
{
var guessDirectory = new DirectoryInfo(
Path.GetFullPath(
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..")));

var projectDirs = guessDirectory.GetDirectories();
foreach (var pd in projectDirs)
{
if (pd.GetFiles("web.config").Length == 1)
{
pathToYourWebProject = pd.FullName;
continue;
}
}
}

var ourDll = Path.Combine(pathToYourWebProject, "bin", "MvcIntegrationTestFramework.dll");
if (!File.Exists(ourDll))
{
File.Copy(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "MvcIntegrationTestFramework.dll"), ourDll);
}

//return new AppHost(pathToYourWebProject, "/__test");
return new AppHost(pathToYourWebProject);
}
}
}
36 changes: 35 additions & 1 deletion MvcIntegrationTestFramework/MvcIntegrationTestFramework.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,28 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MvcIntegrationTestFramework</RootNamespace>
<AssemblyName>MvcIntegrationTestFramework</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand Down Expand Up @@ -68,9 +84,27 @@
<Compile Include="Interception\LastRequestData.cs" />
<Compile Include="Browsing\BrowsingSession.cs" />
<Compile Include="Hosting\AppHost.cs" />
<Compile Include="NameValueCollectionConversions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Browsing\RequestResult.cs" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
33 changes: 33 additions & 0 deletions MvcIntegrationTestFramework/NameValueCollectionConversions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Collections.Specialized;
using System.Web.Routing;

namespace MvcIntegrationTestFramework
{
public static class NameValueCollectionConversions
{
public static NameValueCollection ConvertFromObject(object anonymous)
{
var nvc = new NameValueCollection();
var dict = new RouteValueDictionary(anonymous);

foreach (var kvp in dict)
{
if (kvp.Value.GetType().Name.Contains("Anonymous"))
{
var prefix = kvp.Key + ".";
foreach (var innerkvp in new RouteValueDictionary(kvp.Value))
{
nvc.Add(prefix + innerkvp.Key, innerkvp.Value.ToString());
}
}
else
{
nvc.Add(kvp.Key, kvp.Value.ToString());
}


}
return nvc;
}
}
}
42 changes: 19 additions & 23 deletions MyMvcApplication.Tests/HomeControllerTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.Collections.Specialized;
using System.IO;
using System.Web.Mvc;
using System.Web.Mvc;
using MvcIntegrationTestFramework.Browsing;
using MvcIntegrationTestFramework.Hosting;
using NUnit.Framework;
Expand All @@ -11,15 +8,12 @@ namespace MyMvcApplication.Tests
[TestFixture]
public class HomeControllerTests
{
private static readonly string mvcAppPath = Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory + "\\..\\..\\..\\MyMvcApplication");
private readonly AppHost appHost = new AppHost(mvcAppPath);

[Test]
public void Root_Url_Renders_Index_View()
{
appHost.SimulateBrowsingSession(browsingSession => {
AppHost.Simulate().BrowsingSession(browsingSession => {
// Request the root URL
RequestResult result = browsingSession.ProcessRequest("");
RequestResult result = browsingSession.Get("");
// Can make assertions about the ActionResult...
var viewResult = (ViewResult) result.ActionExecutedContext.Result;
Expand All @@ -34,9 +28,10 @@ public void Root_Url_Renders_Index_View()
[Test]
public void WorkWithCookiesAndSession()
{
appHost.SimulateBrowsingSession(browsingSession => {
AppHost.Simulate().BrowsingSession(browsingSession =>
{
string url = "home/DoStuffWithSessionAndCookies";
browsingSession.ProcessRequest(url);
browsingSession.Get(url);
// Can make assertions about cookies
Assert.AreEqual("myval", browsingSession.Cookies["mycookie"].Value);
Expand All @@ -46,9 +41,9 @@ public void WorkWithCookiesAndSession()
Assert.AreEqual(1, browsingSession.Session["myIncrementingSessionItem"]);
// Session values persist within a browsingSession
browsingSession.ProcessRequest(url);
browsingSession.Get(url);
Assert.AreEqual(2, browsingSession.Session["myIncrementingSessionItem"]);
browsingSession.ProcessRequest(url);
browsingSession.Get(url);
Assert.AreEqual(3, browsingSession.Session["myIncrementingSessionItem"]);
});
}
Expand All @@ -58,28 +53,29 @@ public void LogInProcess()
{
string securedActionUrl = "/home/SecretAction";

appHost.SimulateBrowsingSession(browsingSession => {
AppHost.Simulate().BrowsingSession(browsingSession =>
{
// First try to request a secured page without being logged in
RequestResult initialRequestResult = browsingSession.ProcessRequest(securedActionUrl);
RequestResult initialRequestResult = browsingSession.Get(securedActionUrl);
string loginRedirectUrl = initialRequestResult.Response.RedirectLocation;
Assert.IsTrue(loginRedirectUrl.StartsWith("/Account/LogOn"), "Didn't redirect to logon page");
// Now follow redirection to logon page
string loginFormResponseText = browsingSession.ProcessRequest(loginRedirectUrl).ResponseText;
string loginFormResponseText = browsingSession.Get(loginRedirectUrl).ResponseText;
string suppliedAntiForgeryToken = MvcUtils.ExtractAntiForgeryToken(loginFormResponseText);
// Now post the login form, including the verification token
RequestResult loginResult = browsingSession.ProcessRequest(loginRedirectUrl, HttpVerbs.Post, new NameValueCollection
{
{ "username", "steve" },
{ "password", "secret" },
{ "__RequestVerificationToken", suppliedAntiForgeryToken }
});
RequestResult loginResult = browsingSession.Post(loginRedirectUrl, new
{
UserName = "steve",
Password = "secret",
__RequestVerificationToken = suppliedAntiForgeryToken
});
string afterLoginRedirectUrl = loginResult.Response.RedirectLocation;
Assert.AreEqual(securedActionUrl, afterLoginRedirectUrl, "Didn't redirect back to SecretAction");
// Check that we can now follow the redirection back to the protected action, and are let in
RequestResult afterLoginResult = browsingSession.ProcessRequest(securedActionUrl);
RequestResult afterLoginResult = browsingSession.Get(securedActionUrl);
Assert.AreEqual("Hello, you're logged in as steve", afterLoginResult.ResponseText);
});
}
Expand Down
39 changes: 38 additions & 1 deletion MyMvcApplication.Tests/MyMvcApplication.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,28 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MyMvcApplication.Tests</RootNamespace>
<AssemblyName>MyMvcApplication.Tests</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand Down Expand Up @@ -54,9 +70,13 @@
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="xunit">
<HintPath>..\References\xunit-1.5\xunit.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="HomeControllerTests.cs" />
<Compile Include="NameValueCollectionConversionsTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
Expand All @@ -69,6 +89,23 @@
<Name>MyMvcApplication</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down
Loading

0 comments on commit e246326

Please sign in to comment.