Skip to content

Commit 0a6ff7f

Browse files
committed
Updated the readme to point to the documentation
1 parent a1d2018 commit 0a6ff7f

1 file changed

Lines changed: 5 additions & 250 deletions

File tree

README.md

Lines changed: 5 additions & 250 deletions
Original file line numberDiff line numberDiff line change
@@ -11,257 +11,12 @@ The motivation behind this library is to provide a way to test MVC actions quick
1111

1212
This library was inspired by the [MVCContrib.TestHelper](http://mvccontrib.codeplex.com/wikipage?title=TestHelper) library.
1313

14-
Installation
15-
------------
14+
Documentation
15+
-------------
1616

17-
You can install this library using NuGet into your Test Library; it will automatically reference System.Web and System.Web.Mvc (via NuGet packages, sorry it also installs a heap of other dependencies - it would be cool if Microsoft provided a package with just the MVC dll!) for you.
18-
19-
If you are using ASP.NET MVC 4 then:
20-
21-
Install-Package TestStack.FluentMVCTesting
22-
23-
If you are using ASP.NET MVC 3 then:
24-
25-
Install-Package TestStack.FluentMVCTesting.Mvc3
26-
27-
Known Issues
28-
------------
29-
30-
If you get the following exception:
31-
32-
System.Security.VerificationException : Method FluentMVCTesting.ControllerExtensions.WithCallTo: type argument 'MyApp.Controllers.MyController' violates the constraint of type parameter 'T'.
33-
34-
It means you are referencing a version of System.Web.Mvc that isn't compatible with the one that was used to build the dll that was generated for the NuGet package. Ensure that you are using the correct package for your version of MVC and that you are using the [AspNetMvc packages on nuget.org](https://nuget.org/packages/aspnetmvc) rather than the dll from the GAC.
35-
36-
Examples
37-
--------
38-
39-
### Recommended class structure
40-
41-
The following code snippet is an example for how to set up a test class to use FluentMVCTesting using NUnit, this is simply to get you started quickly, in reality you can use it how you like and with any unit testing framework of your choice.
42-
43-
using MyApp.Controllers;
44-
using NUnit.Framework;
45-
using TerseControllerTesting;
46-
47-
namespace MyApp.Tests.Controllers
48-
{
49-
[TestFixture]
50-
class HomeControllerShould
51-
{
52-
private HomeController _controller;
53-
54-
[SetUp]
55-
public void Setup()
56-
{
57-
_controller = new HomeController();
58-
}
59-
60-
[Test]
61-
public void Render_default_view_for_get_to_index()
62-
{
63-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView();
64-
}
65-
}
66-
}
67-
68-
### Basic syntax
69-
70-
As you might have gathered from the previous code snippet the entry point to the library is the `WithCallTo` extension method on the MVC `Controller` class; inside of that method call you simply pass in a lamdba expression that takes the controller to make the action call that you are trying to test. From there you can use intellisense to guide your testing.
71-
72-
### Model binding errors
73-
74-
If you want to test what happens when the default model binding (or indeed any custom model binding or validation that you perform) has left errors in `ModelState` when your action is called you can simply use the `WithModelErrors()` extension method, e.g.:
75-
76-
_controller.WithModelErrors().WithCallTo(c => c.Index()).ShouldRenderDefaultView();
77-
78-
### Child actions
79-
80-
If you want to check that the action being called has the `[ChildActionOnly]` attribute then use `WithCallToChild()` rather than `WithCallTo()`, e.g.:
81-
82-
_controller.WithCallToChild(c => c.Index()).ShouldRenderDefaultView();
83-
84-
### Empty result
85-
86-
_controller.WithCallTo(c => c.Index()).ShouldReturnEmptyResult();
87-
88-
### Redirect to url
89-
90-
_controller.WithCallTo(c => c.Index()).ShouldRedirectTo("http://www.google.com.au/");
91-
92-
### Redirect to route name
93-
94-
_controller.WithCallTo(c => c.Index()).ShouldRedirectToRoute("RouteName");
95-
96-
### Redirect to action within the same controller
97-
98-
There are a number of ways that you can specify this test, depending on the signature of the action you are redirecting to.
99-
100-
If you are redirecting to an action that takes no parameters, or takes a single int parameter, then you can use a method group, which is the tersest specification (you don't need to specify the parameters to the action), e.g. if these are two actions in the controller you are testing:
101-
102-
public ActionResult ActionWithNoParameters()
103-
{
104-
return new EmptyResult();
105-
}
106-
public ActionResult RedirectToActionWithNoParameters()
107-
{
108-
return RedirectToAction("ActionWithNoParameters");
109-
}
110-
111-
Then you can write this test:
112-
113-
_controller.WithCallTo(c => c.RedirectToActionWithNoParameters())
114-
.ShouldRedirectTo(c => c.ActionWithNoParameters);
115-
116-
I can explicitly define whatever signatures I want to allow this terser syntax, but obviously the different permutations that are possible are mind-boggling and it wouldn't be helpful for any custom types in your project. Unfortunately, despite best efforts I couldn't figure out a way to generically specify these definitions - if anyone has ideas for how to do this let me know!
117-
118-
If you have 1-3 parameters being passed into the action being redirected to then you can still use the method group, but you need to specify the types being passed into the action, e.g. if you have the following controller action being redirected to:
119-
120-
public ActionResult SomeAction(string param1, int param2, bool param3) {}
121-
122-
Then you can write the following test for the redirect:
123-
124-
_controller.WithCallTo(c => c.Index())
125-
.ShouldRedirectTo<string, int, bool>(c => c.SomeAction);
126-
127-
If you have more than three parameters, or you are uncomfortable with that syntax then you can specify a lambda with a call to the action you want and pass in dummy values for the parameters, e.g. for the previous example:
128-
129-
_controller.WithCallTo(c => c.Index())
130-
.ShouldRedirectTo(c => c.SomeAction(null, 0, false));
131-
132-
You can also pass through a MethodInfo object against the method you are redirecting to, e.g.:
133-
134-
_controller.WithCallTo(c => c.Index())
135-
.ShouldRedirectTo(typeof(HomeController).GetMethod("SomeAction"));
136-
137-
If you use this option (I don't recommend it because it uses a "magic" string so if you change the action name then the string won't change, although at least the test will break because the Method name will no longer be valid; in saying that if you change your parameters more often than the action name this might be a better option) be careful that you don't get an AmbiguousMatchException if there are multiple actions with that name.
138-
139-
At this stage there isn't support for the `[ActionName()]` attribute or simply passing through a string to check against the action name, but if either are important to you feel free to add an issue in this GitHub project and I can add them.
140-
141-
### Redirect to action in another controller
142-
143-
If you are redirecting to an action in another controller, then there are two syntaxes that you can currently use (similar to the last two mentioned above):
144-
145-
_controller.WithCallTo(c => c.Index())
146-
.ShouldRedirectTo<SomeOtherController>(c2 => c2.SomeAction());
147-
148-
_controller.WithCallTo(c => c.Index())
149-
.ShouldRedirectTo<SomeOtherController>(typeof(SomeOtherController).GetMethod("SomeAction"));
150-
151-
### View results (where the view name is the same as the action name - explicitly or via an empty string)
152-
153-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView();
154-
155-
// Or, if you want to check a partial is returned
156-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultPartialView();
157-
158-
### View results
159-
160-
_controller.WithCallTo(c => c.Index()).ShouldRenderView("ViewName");
161-
162-
// Or, if you want to check a partial is returned
163-
_controller.WithCallTo(c => c.Index()).ShouldRenderPartialView("ViewName");
164-
165-
Unfortunately, we couldn't think of a way to get rid of the magic strings here so where possible use the default ones above.
166-
167-
See below for model testing.
168-
169-
### Files
170-
171-
_controller.WithCallTo(c => c.Index()).ShouldRenderFile();
172-
173-
_controller.WithCallTo(c => c.Index()).ShouldRenderFile("content/type");
174-
175-
### Http status codes
176-
177-
_controller.WithCallTo(c => c.Index()).ShouldGiveHttpStatus();
178-
179-
_controller.WithCallTo(c => c.Index()).ShouldGiveHttpStatus(404);
180-
181-
### JSON
182-
183-
_controller.WithCallTo(c => c.Index()).ShouldReturnJson();
184-
185-
_controller.WithCallTo(c => c.Index()).ShouldReturnJson(data =>
186-
{
187-
/* Assertions on the data being turned into json (data) */}
188-
);
189-
190-
### Model tests
191-
192-
If you assert that the action returns a view of some sort there are some other methods that you can call (seen easily using intellisense). These allow you to check the model, e.g.:
193-
194-
// Check the type of the model
195-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
196-
.WithModel<ModelType>();
197-
198-
// Check that a particular object was passed through as the model
199-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
200-
.WithModel(expectedModel);
201-
202-
// Check that the model that was return passes a predicate
203-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
204-
.WithModel<ModelType>(m => m.Property1 == "hello");
205-
206-
// Make assertions on the model
207-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
208-
.WithModel<ModelType>(m => {/* Make assertions on m */});
209-
210-
Note: if you use any of these model tests then it will check that the model passed through isn't null.
211-
212-
### Model error tests
213-
214-
Once you have made assertions about the model you can then make assertions that particular model errors are present for properties of that model. While it's not generally the best idea to add validation logic to controllers ([doing it unobtrusively is best](http://robdmoore.id.au/blog/2012/04/27/unobtrusive-validation-in-asp-net-mvc-3-and-4/)), sometimes it's useful.
215-
216-
// Check that there are no model errors
217-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
218-
.WithModel<ModelType>().WithNoModelErrors();
219-
220-
// Check that there is a model error against a given property in the model
221-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
222-
.WithModel<ModelType>().AndModelErrorFor(m => m.Property1);
223-
224-
// Check that there is a model error against a specific key
225-
// Avoid if possible given it includes a magic string
226-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
227-
.WithModel<ModelType>().AndModelError("Key");
228-
229-
// You can chain these model error calls and thus check for multiple errors
230-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
231-
.WithModel<ModelType>()
232-
.AndModelErrorFor(m => m.Property1)
233-
.AndModelErrorFor(m => m.Property2);
234-
235-
You can also make assertions on the content of the error message(s); these methods will look for any error messages against that particular model state key that match the given criteria:
236-
237-
// Equality
238-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
239-
.WithModel<ModelType>()
240-
.AndModelErrorFor(m => m.Property1).ThatEquals("The error message.");
241-
242-
// Start of message
243-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
244-
.WithModel<ModelType>()
245-
.AndModelErrorFor(m => m.Property1).BeginningWith("The error");
246-
247-
// End of message
248-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
249-
.WithModel<ModelType>()
250-
.AndModelErrorFor(m => m.Property1).BeginningWith("message.");
251-
252-
// Containing
253-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
254-
.WithModel<ModelType>()
255-
.AndModelErrorFor(m => m.Property1).Containing("e error m");
256-
257-
You can chain the error property checks after any of these checks (you can only perform one of the checks though):
258-
259-
_controller.WithCallTo(c => c.Index()).ShouldRenderDefaultView()
260-
.WithModel<ModelType>()
261-
.AndModelErrorFor(m => m.Property1).ThatEquals("The error message.")
262-
.AndModelErrorFor(m => m.Property2);
17+
Please see [the documentation](http://teststack.github.com/pages/fluentmvctesting.html) for installation and usage instructions.
26318

26419
Any questions, comments or additions?
265-
--------------------------
20+
-------------------------------------
26621

267-
Leave an issue on the [GitHub project](https://github.com/TestStack/TestStack.FluentMVCTesting/issues) or send a [pull request](https://github.com/TestStack/TestStack.FluentMVCTesting/pulls).
22+
Leave an issue on the [issues page](https://github.com/TestStack/TestStack.FluentMVCTesting/issues) or send a [pull request](https://github.com/TestStack/TestStack.FluentMVCTesting/pulls).

0 commit comments

Comments
 (0)