We were unable to load Disqus. If you are a moderator please see our troubleshooting guide.

Mike Eshva • 11 years ago

Thank you for your article! I'm learning testing of MVC applications and it helps me.
With Autofac you can use IContainer.IsRegistered(Type) in place of your IContainer.Resolve(Type). The intention is more clear and it should not instantiate an object.
In my application I use injection of external dependencies through action parameters. I've wrote a similar test for my case. You just need to get all action method infos and check through the container their types are registered. But you need to filter form's parameters out. I do filtering by the parameter's type full name (it should not start with 'System' and should not ends with 'ViewModel'). For every application this filtering criteria can be unique.

rob • 11 years ago

If you use IsRegistered won't that just check that the controller is registered rather than all it's dependencies and their dependencies etc. down the chain?

Thanks for the comment! :)

Stephen • 13 years ago

It's a good test.

But not for that reason.

This is an integration test. It's focus is on your application, not the individual controllers.

At each level of your application (i.e. components at an individual basis, components used together, end to end, etc) tests should be explicit rather than programmatically determined.

Otherwise, what's testing the tests? (in terms of explicit tests, it's the human at the time of writing/changing that test)

The child components to the thing you are testing can be tested dynamically (using mocks, reflection) because those child components have their own separate explicit tests.

Also, having constantly changing tests can also be a sign of bad API (as well as a sign of bad testing).

Which is very useful once you start to consider tests as more than just validation, but also as a way of making your software tangible.

Note that I do say this coming from my background of dynamically typed languages :p

Rob • 13 years ago

To be honest with you Steve, I've always felt uncomfortable about people getting really picky about whether a test is a unit test, or an integration test or a … I don't think it's productive. Don't get me wrong, if you are doing tests on a single module/class then I think you should consistently mock all or none of the dependencies (otherwise it will be a mess and you will have no idea what you are and aren't testing).

But, for instance I will always test my data repositories with actual round trips to the database because there is no point in mocking out the database – it doesn't give you any value. I will also combine these integration/unit (integration with the database, but testing a single unit – an individual repository method) tests with my "unit tests" project because they don't take a huge amount of time to execute.

I know a lot of people will say you should separate integration from unit tests, but I don't think that makes sense unless the integration tests take a long time to execute. This is why I don't like people being really particular in identifying what type of test something is – it doesn't mean anything valuable!

Re: explicit tests I agree that if your implementation is "magic" in that it uses meta programming or other terse language features that the test should have a different more explicit implementation (e.g. passing all the different test cases to a unit test method) in order to give a good value test. But, if the implementation is explicit, as is the case in terms of specifying dependencies to a controller then I think it's perfectly valid, and frankly a good idea (to save time and make your code more maintainable) to make the tests programmatic.

In terms of what tests the tests I disagree with your assertion. In fact, it's the code that tests the tests and vice versa. When a human writes the test they are merely specifying their intent on the code design, what actually tests the test is writing the code implementation that passes the test. If the programmer writes an implementation that is correct, but the test (incorrectly) fails then they will modify the test to correct it because the test was wrong. The same applies in reverse when changing the implementation to pass a failing test.

Agreed re: bad API as well as bad tests.

Stephen • 13 years ago

So when I said "integration test", my intention was more to point out the focus of the test rather than this concept of only one thing vs many things in the one test.

So it's integration in that you're testing the things are helping with the task the parent thing needs to do. Rather than testing those things in their own right.

An idea that becomes important if you write everything as a thing providing functionality, rather than a thing solving a problem. (subtle difference).

When I say humans test the tests, that also involves ensuring against false positives, which by their very nature can't be seen by the computer.

As for programmatic tests. My rant doesn't cover the test in your blog post. That is a good test that makes sure that all your controllers instantiate. It's likely controllers are added in the future and hence you want your test to keep up with that without the developer knowing that they need to edit the test.

My problem with programmatic tests is where code paths inside the test itself is determined via complex rules.