From my initial readings on unit testing (I'm a beginner) it is wise to put all of your setups and tests in a separate project from the code being tested. This seems ideal to me, as well. However, I've recently begun reading The Art of Unit Testing, trying to discover how to break dependencies on things such as database calls. The methods offered involve changing areas of the test code, such as adding specific interfaces and "stub" methods to the production code. This seems to defeat some of the good things about keeping tests and production code separate.
Is there any recommended dependency-breaking technique that doesn't involve changing production code?
There is no way to break dependencies without making some sort of change. What is important is that the changes you make don't change the behavior of production code in production, and that you aren't introducing worse dependencies.
By definition, the dependencies need to be broken in the production code to make it more testable, i.e., to make the production code more testable you need to change the code to make it less coupled to actual implementations. This will allow you to substitute mock objects for the real objects in the class under test in your tests. This removes the dependency on other production classes that the class under test depends on.
If you've written loosely-coupled production code -- code that relies on interfaces rather than implementations, that uses factories and dependency injection to create objects rather than direct instantiation -- then you may only need to make small changes or none at all to your production code. If not, then you will need to make those types of changes. This isn't a bad thing, however, as it will improve your design by reducing coupling between classes. The cost of this will be a few extra (small) classes and/or interfaces that make the isolation possible.
If you use TDD (Test Driven Development/Design), the types of construction that you use in your production code will change to make it more naturally testable. This is one of the ways that TDD works to improve design as well as incorporate testing into your code.
Note that you shouldn't need to introduce coupling or dependencies in your production code to your test code. Your test code will obviously be dependent on production and you may need to refactor the dependencies in production to make it more testable, but if your production code "knows" anything about how it's being tested, you've probably done something wrong. You've probably introduced artificial interfaces when you should be using dependency injection.
We use Spring along with factories to break dependencies. With Spring's dependency injection, changing from development and testing, to production is just a different XML file.
Related
I'm working with a large mature php codebase that I'm considering making a case for automated testing for to the management. As part of this I want to have the core of a usable testing suite in place to demo the impacts on our completion times ect. Only thing is, I'm pretty much a novice at automated testing myself and theres a couple of real life considerations I'm not altogether clear on.
For one thing how do I include my tests in git? I don't want to push them live!
For another I clearly don't want to create dependencies in the production code on a testing tool. So should I be writing the tests to load the main application into them as a preamble to the actual tests? (This would seem to imply a mirror directory structure for tests is needed in our development environments).
Lastly I am leaning toward PHPtest and/or selenium to run the show. In particular I want to test browser test results including html and subsequent js and ajax operations. Selenium seems ideal for that but I'm unclear on how I would integrate it into the codebase. I assume its Javascript but I'm unclear on that. The remaining features that aren't user accessible would then be tested by PHPtest, a fairly small number of items I would assume. Does that seem in any way sane?
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?
What is the any use of Dependency Injectors except writing unit test friendly programs?
I have used it in several projects and I like this approach. However I was wondering what is the real use of this pattern? Give me just one use but with proper explanation and code if possible.
Plenty of information if you Google it. From Wikipedia:
Advantages
Because dependency injection doesn't require any change in code behavior it can be applied to legacy code as a refactoring. The result is more independent clients that are easier to unit test in isolation using stubs or mock objects that simulate other objects not
under test. This ease of testing is often the first benefit noticed when using dependency injection.
Dependency injection allows a client to remove all knowledge of a concrete implementation that it needs to use. This helps isolate the client from the impact of design changes and defects. It promotes reusability, testability and maintainability.
Dependency injection can be used to externalize a system's configuration details into configuration files allowing the system to be reconfigured without recompilation. Separate configurations can be written for different situations that require different implementations of components. This includes, but is not limited to, testing.
Reduction of boilerplate code in the application objects since all work to initialize or set up dependencies is handled by a provider component.
Dependency injection allows concurrent or independent development. Two developers can independently develop classes that use each other, while only needing to know the interface the classes will communicate through. Plugins are often developed by third party shops that never even talk to the developers who created the product that uses the plugins.
Let's say I have a Visual Studio solution with a Web project, a BLL project, and a DAL project. I'm trying to follow the repository pattern keeping my SQL code in the DAL with an interface that is referenced by the BLL.
I have a handful of common solutions for things such as error handling, usage logging, and other things that can be considered utility functions (i.e. not in the business spec). I'm keeping these in a Common project.
Here are a few ideas I've had with regards to structuring the Common project...
Bundle SQL with logic in a given class
Create a layered solution within the Common project
Discard the Common project and put utility functions in with BLL/DAL
Is one of these ideas better/worse than the other? Does anyone have a better solution?
It's worth noting that these utility functions will be reused in a variety of other applications.
Instead of creating a Utilities project which will be used have you thought about creating something that can provide a service? You might want to look at Aspect Oriented Programming. Red flags went up when I saw you listing off your examples error handling, logging, etc. Those scream AOP.
But if you want to stick with your layout.
I think I would go with 2, assuming that means restructuring the utilities project to be more Cohesive.
I don't understand (please clarify and I will edit my post)
Bundle SQL with logic in a given class
As for:
Discard the Common project and put utility functions in with BLL/DAL
I would be against doing so. If this logic is truly going to be repeated there is no need to push it back into your projects. This will lead to duplicate code and increased maintenance.
Side Note:
Just as a lessons learned, the only way Utilities projects work, are if you are the only developer or it is well documented and well designed. Sometimes utilities are too programmer specific, or are written in a way that only benefits a particular coders style.
I have seen countless times people rework their infrastructure pulling out all kinds of utilities, only to see their utilities project never get used. Make sure the "utilities" you are creating are truly useful to other people.
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.