I prefer to keep my handlers free from ASP.NET infrastructure that is very hard to test (yes, even in ASP.NET Core). But sometimes it happens and you have a dependency like UserManager (I'd like to know one day why it's not an interface), HttpContext, etc. and unit-tests are turned into a mocking-hell.
I tried using integration testing to deal with it by creating a TestServer and having all the ASP.NET infrastructure initialized for every api call. It works quite well but sometimes seems like an overkill if I want to test simple logic of my handler. And while it solves technical problem of mocking ASP.NET infrastructure, it keeps architectural problem (if you consider it so) of having ASP.NET infrastructure into your handlers.
I'd like to know what are the recommended approaches to deal with it?
I feel your pain. I stumbled across a fantastic blog post from Jimmy Bogard that handles this problem by using what Martin Fowler calls Subcutaneous Tests. I will leave the deep explanation to those experts but in a nutshell subcutaneous tests simply avoid all the difficult to test aspects of the UI.
Shameless plug: I am currently in the process of writing up a wiki that demonstrates these patterns in a sample end-to-end project on github. It's not difficult to follow but is probably too much code to post for a SO answer.
To Summarize:
If you are using MediatR correctly your controllers should be very thin which makes testing them pointless.
What you want to test are your handlers.
However, you want to test your handlers as part of your real world pipeline.
To Solve:
Wrap the http request in a transaction.
Build a test fixture that mimics the applications Startup.cs
Setup a test db server to execute queries and commands against but also is reset after each test.
That's basically it. Everytime you run an integration test against one of your handlers:
The hosting environment is mocked but your application is started up in a real world test.
Your query or command is wrapped in a transaction mimicking your DbContext.
The handler is executed against a real database and then reset.
I would add more code examples to my answer but between the blog post and the wiki I provided, it is much easier to follow the code examples there.
Edit 8/2021:
Stick with the source. Jimmy Bogard keeps the contoso university project current on his github page. Another great and a little more advanced example is the modular monolith project by Kamil Grzybek. That also is updated regularly on his github page.
Mediatr or no, you should always try to have only very basic pass this along logic in your controllers and call injected business logic classes from there to do the actual work. As you inject them with interfaces to this business logic, your controllers' dependencies are easily mocked in your unit tests, and your tests can focus on if they implement those interfaces properly and do only the basic work of routing input/output. And your actual business logic can be tested even easier.
For those classes that are static, for instance for reading the web.config settings, one strategy that I like a lot is make an interfaced wrapper class around them. While ConfigurationManager is static, I can still just write a regular class with an interface that I put methods or properties on to read a specific setting (preferably semantically named) from the Configuration Manager. Now I can easily mock any configured setting (or absence of it) in my test by just mocking the interface and setting up different return values.
I'd say it depends on the level of confidence you want to get in the end. If you want to make sure the whole system works as expected, then integration tests using a TestServer are probably the way to go.
One advantage of MediatR, though, is it allows you to decouple your business logic from the application using it, which is why at the very top level, let's say in controllers, there's no logic but just a delegation to the mediator.
That being said, you're right that sometimes your logic needs information from the hosting application. An example would be the user making the request, which is accessible in the HTTP context.
In that case, if you want to avoid having to set up a test HTTP server to test your logic works, you could represent that information in an abstraction and your handler would then take a dependency on that abstraction. Your tests could then mock that dependency while using the real system for everything else.
Does that make sense?
Related
I am building a a web app with Spring MVC and hibernate. I am struggling with scope. E.g., create parent and children on same interface requires resetting child bean after first child created. Spring MVC does not allow removal of bean from session scope. At the same time, shifting children across multiple request scopes is not practical. I need a conversation scope.
I am now looking at Spring Web Flow as a solution. However, it is poorly documented and seems to depend entirely on xml configuration. Both these features seem to suggest it is an older and perhaps not well supported project.
Can anyone advise on whether I should invest time learning Spring Web Flow, or perhaps suggest alternative solutions that tie into Spring MVC.
I've spent some time on this now.
I think the reason for xml as opposed to annotation is design. Once one has one's head around it, the flow config is simple and leads to very fast development.
Yes, it seems to be in maintenance mode, but the design is solid and reliable and development seems to be very efficient. Learning curve is a little steep, especially if integrating into an extant webapp, but I was up and running in about three days.
Webflow's own documentation is not great, but the tutorial linked here is excellent.
UPDATE
5 months on and I have built a complete assessment system (i.e test/exam system). My background is in IT and I have a Ph.d in psychology.
The system I built has been thoroughly tested and stress tested.
Advantages of webflow.
A person can start a test, give up and restart in the same session with no problems since flowState takes care of everything
There is full control of when the user can use the back button and how far back the user can go. Returning to state after an illegitimate backbutton usage is easy and user friendly.
Stress test performance is excellent
Configuration is easy. I spent almost no time dealing with design or bug issues related to Webflow.
FRom a higher level design perspective, there were no use cases that were required from a business perspective that could not be implemented.
Disadvantages
Since all objects are serialized before presentation on the webpage, you have to be very careful about how you cache objects if you take them out of the flowState beans.
Spring Web Flow appears to be maintained, but not in active development. I see a handful of commits, mostly updating dependency versions and fixing bugs.
You are correct that the configuration of the flow is XML-only, which I believe is the single biggest drawback of this aging Spring project. I have searched for a DSL or dynamic builders and I did not find anything.
Having said that, I'd give it a shot. Simple flows—even dynamic and inherited flows—are possible. In addition, the backing form and the POST-Redirect-GET Pattern implementations may be useful to you. That last technique prevents form resubmission when you use the browser back button.
I have been looking at webflow myself (for the past day, ~16 hours) since after I seen "primefaces".
Webflow offers varying types of states and transitions to those states. States can have a view associated with it (HTML page or JSP page -> primefaces comes in here). Each JSP pages are templates, like PHP just using java and xhtml. Using primefaces components the interaction between the client and server "seems" almost automated (a plus for quick development). Webflow also offers flow variables, which is a java data object. The flow variable can have the life over the flow and is used by views and templates. Webflow allows you to control transitions between all states.
However, I think this is where I stop my research. First, what is the advantage of webflow over a good client side web application using AngularJS with Spring MVC (#RequestMapping), if flow control is needed build it on the client. If you would like a variable that exists over the lifetime of the session, make a javascript variable, however if the variable needs to only exist on the server and you would like to use templates, then webflow seems like a ideal choice.
If you need a state-ful webapp then it might be a good idea to checkout Spring HATEOAS type concept (passing the state as a parameter to the client), and that parameter refers to limited time availability variables. Less coding and seems to conform to internet model better.
The question in short is that we are stumbling upon BDD definitions that more or less require different states - which leads to the necessity for a mock of sorts for ASP.NET/MVC - I know of none, which is why I ask here
Details:
We are developing a project in ASP.NET (MVC3/Razor engine) and are using SpecFlow to drive our development.
We quite often stumble into situations where we need the webpage under test to perform in a certain manner so that we can verify the behavior, i.e:
Scenario: Should render alternatively when backend system is down
Given that the backend system is down
And there are no channels for the page to display
When I inspect the webpage under test
Then the page renderes an alternative html indicating that there is a problem
For a unit test, this is less of an issue - run mock on the controller bit, and verify that it delivers the correct results, however, for a SpecFlow test, this is more or less requiring alternate configurations.
So it is possible at all, or - are there some known software patterns for developing webpages using BDD that I've missed?
Even when using SpecFlow, you can still use a mocking framework. What I would do is use the [BeforeScenario] attribute to set up the mocks for the test e.g.
[BeforeScenario]
public void BeforeShouldRenderAlternatively()
{
// Do mock setups.
}
This SO question might come in handy for you also.
You could use Deleporter
Deleporter is a little .NET library that teleports arbitrary delegates into an ASP.NET application in some other process (e.g., hosted in IIS) and runs them there.
It lets you delve into a remote ASP.NET application’s internals without any special cooperation from the remote app, and then you can do any of the following:
Cross-process mocking, by combining it with any mocking tool. For example, you could inject a temporary mock database or simulate the passing of time (e.g., if your integration tests want to specify what happens after 30 days or whatever)
Test different configurations, by writing to static properties in the remote ASP.NET appdomain or using the ConfigurationManager API to edit its entries.
Run teardown or cleanup logic such as flushing caches. For example, recently I needed to restore a SQL database to a known state after each test in the suite. The trouble was that ASP.NET connection pool was still holding open connections on the old database, causing connection errors. I resolved this easily by using Deleporter to issue a SqlConnection.ClearAllPools() command in the remote appdomain – the ASP.NET app under test didn’t need to know anything about it.
My company has a fairly old fat client application written in Delphi. We are very interested in replacing it with a shiny new web application. This will make maintenance a breeze and many clients want a web application.
The application is extremely rich in domain knowledge, some of which is out of our control. Our clients use the program to manage their own clients and report them to the government. So an inaccurate program is a pretty big thing. The old program has no tests. We are not sure yet if we will implement automated testing with the new one.
We first planned to basically start from scratch. But we are short handed and wanting to basically get everyone on the web as soon as possible. So instead of starting from scratch we've decided to try to make use of the legacy fat-client database.
The database is SQL Server and can be used in SQL Server 2008 easily. It is very rich in stored procedures, functions, a few triggers, and lots of tables with over 80 columns... But it is decently normalized. We want for both the web application and fat client to be capable of using the same database. This is so that if something breaks badly in the web application, our clients can still use the fat client and connect to our servers. After the web application is considered "stable", we'd deprecate the fat client.
Has anyone else done this? What tips can you give? We want to, after getting everyone on the website, to slowly change the database structure to take care of some design deficiencies. What is the best way to keep this in a data access layer so that later changes are easy?
And what about actually making the screens? Is there any way easier than just rewriting an 80 field form in ASP.Net? Are there any tools that can make this easier?
The current plan is to use ASP.Net WebForms (.Net 3.5). I'd really like to use MVC, but no one on the team knows it including me.
We are not sure yet if we will implement automated testing with the
new one.
Implement automated testing. What's the point in replacing one buggy program with another?
Good question, but "Slowly change" the db structure after getting everyone on the website, sounds like a joke...
I would rather take the opportunity to create a fresh db structure, write a bulletproof migration script for you db, that you can try out and rewrite a zillion times without any side effect fro your clients, and then write whaterver you want (fat/web) on the new db, have it tested and migrate everyone when it's ready.
I have a couple suggestions:
1) create a service layer to abstract away the dependance on the DAL. In a situation as you describe having a layer of indirection for the UI and BLL to rely on makes DB changes much safer.
2) Create automated tests (both unit and integration), especially if you plan on making fairly significant changes to the Domain or Persistance layers (BLL/DAL). To make this really easy you should always try to program to an interface. This makes your code more flexible as well as letting you use mocking frameworks (Moq is one I like) to ensure your tests truely are unit tests and not integration tests.
3) Take a look at DDD (http://domaindrivendesign.org/) as it seems to fit pretty well with the given scenario. At the very least there are some very useful patterns that can help make your application more flexible.
4) MVC isnt very hard to learn at all, it is however an easy way to get unit testing setup for the UI as a result of the MVC architecture (testing the controller and not the view). That said, there is no reason you couldn't unit test web forms, its just a bit more work. MVC really is just a UI framework/design pattern (more Model2 but we can ignore that for now). It gets you closer to the metal so to speak as you will be writting a lot more HTML and using a Model (the 'M') for passing data around.
For DDD take a look at Eric Evans book: http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=sr_1_1?s=books&ie=UTF8&qid=1317333430&sr=1-1
Hope that helps
ASP.NEt forms is a no starter, is completely inappropriate for something like this. I recommend to start with something like Creating an OData API for StackOverflow including XML and JSON in 30 minutes, then build your Web app on top of that (ie. push it to the client, use JQuery/Silverlight).
Disclaimer:
This is the first time I am asking a question that might be classified as subjective. As English is not my first language, it is hard to phrase this right. So please feel free to edit the question in order to make it clearer, or to point me at other ways for asking this.
Intro:
David Ebbo (architect on the ASP.NET team) just posted on Register your HTTP modules at runtime without config using the seemingly undocumented PreApplicationStartMethod assembly level attribute
I have mixed feelings about it.
On the one hand it is good to be able to do things as early in the application startup phase as possible.
On the other hand: Does it suffice? Do we need a PrePreApplicationStartMethod allowing to fiddle with the PreApplicationStartMethod behaviour? What about expansion to non-assembly use (for instance, NuGet already works around the single-use-per-assembly restriction of PreApplicationStartMethod)?
Question: Besides using it for config-less startup, what do you think of the PreApplicationStartMethod attribute?
I think one of the good usages for this is that it allows someone who is writing a 3rd party assembly, or a team that is working on an assembly that will be used in many projects, to be able to use this attribute to initialize stuff w/o requiring the end user/developer to create anything in the global.asax in the application startup events.
There are lots of app specific stuff that people like to/need to configure in global.asax, but if you are creating a DLL, you no longer have to make the user configure your classes in the global.asax, you can just put all your logic in your own init/bootstrap function and rely on asp.net to call your init logic when the app starts.
We're getting some errors, if we try to test something with the asp.net membership framework. It seems that it can't instantiate the asp.net membership environment and so, it can't access all the profiles, users and so on.
Has anybody seen a similar problem? Or is it working for someone?
Cheers,
Steve
If you are depending on external resources such as your database and the configuration files (used when using the ASP.NET membership) you aren't writing very effective unit tests. You will have to keep everything in sync including the data in the database. This because a maintenance nightmare.
If you want to test this way, I recommend setting up your configuration to have membership (you can grab this from your application). You then will also want to set up a test database to connect to. It needs to be populated with fake data, so you'll need scripts to make sure the data is consistent.
I would however recommend that you take the approach of doing more proper unit tests. When we refer to a "unit test" we mean testing a very small piece of code at a time. This code should not depend on anything else, so what you need to do is use interfaces and use fakes, stubs, or mocks so that your tests scope is enclosed to a single unit of code.
If you want to go this route I highly recommend reading Working Effectively with Legacy Code. There are also plenty of other books and resources which talk about how to find seams and decouple your code so you're able to test it. Once you get the hang of unit testing you'll be glad you looked into this.
The test framework is looking at the test project's web.config file which likely doesn't have the right configuration. You should really write interfaces around the authentication/membership providers and write some dummy implementations to test with.
Going on from Benrick's answer - I recommend you take a look at the ASP.NET MVC project - this has examples of the interfaces and wrappers you would need to have to properly unit test your code.
As the comments in the AccountController.cs file state:
The FormsAuthentication type is sealed and contains static members, so it is difficult to unit test code that calls its members. The interface and helper class below demonstrate how to create an abstract wrapper around such a type in order to make the AccountController code unit testable.