21

To me this is a totally irrelevant unit-test and I don't understand why someone would spent time writing it, since there is very little value to gain from it. I would know perfectly well if this controller returned the wanted type by executing the method in a browser. Really, do you believe a test is needed for this and why ?

public class ConstituencyControllerTests
{
    private ConstituencyController _constituencyController;
    private Mock<IConstituencyService> _IConstituencyServiceMock;

    public ConstituencyControllerTests() {
        _IConstituencyServiceMock = new Mock<IConstituencyService>();
    }

    [Test]
    public async Task I_Check_For_Return_Type_And_Result() {
        _constituencyController = new ConstituencyController( _IConstituencyServiceMock.Object );

        var result = await _constituencyController.Get();
        var content = ( (dynamic)result ).Content;

        Assert.IsEmpty( content );
        Assert.IsInstanceOf( typeof( System.Web.Http.Results.OkNegotiatedContentResult<IEnumerable<ListOfConstituencies>> ), result );
        _IConstituencyServiceMock.Verify( x => x.ListOfConstituencies(), Times.Once() );
    }
}
  • 6
    Don't agree with that @gnat. This is not about language constructs necessarily but about the type of the result returned by a controller. While it may boil down to sort of the same thing when you have no inheritance hierarchy, it becomes an altogether different beast when the controller expects Ancestors to be returned, the controller returned Person and now Person is changed to descend not from Ancestor, but PeopleAncestor... Also answers why testing such a method may be a good idea... ;) Unit tests are meant to pick up on situations where a change in one thing c/would break something else. – Marjan Venema Dec 19 '16 at 11:48
  • 1
    stackoverflow.com/q/8818207/5934037 – Laiv Dec 19 '16 at 12:21
  • Tend to agree, I typically don't spend much time unit testing the entry points of the application. It is like unit testing a main method of a console application. just makes very little sense to me. – Mvision Jan 30 at 10:58
29

They key point is here :

I would know perfectly well if this controller returned the wanted type by executing the method in a browser

Unit-tesing is about automation of non-regression testing simple units of code, not that you look yourself. You don't want to do yourself always unit tesing in your application.

EDIT : Adding @anotherdave comment :

It's about ease of scaling. Testing one controller in a browser may be OK; what about 10, 20, 50 controllers? You'll write the test once; you may need to update it when you change the controller, which is overhead. But how often do you deploy? Surely a manual check each time there is much more overhead that the test

As an alternative to @Vladislav's answer, unit testing absolutely everything can be an overkill, and really undesirable. If you need something lighter you can do higher level non-regression testing using Selenium. Surely you'll get less coverage than unit-testing, but you can get a raisonable coverage which cost way less time doing unit-testing and is more flexible.

That is, if you unit-test everything you have to update one or more tests each time you modify a simple element.

  • 4
    Also to add re: I would know perfectly well if this controller returned the wanted type by executing the method in a browser. — it's about ease of scaling. Testing one controller in a browser may be OK; what about 10, 20, 50 controllers? You'll write the test once; you may need to update it when you change the controller, which is overhead. But how often do you deploy? Surely a manual check each time there is much more overhead that the test. – anotherdave Dec 19 '16 at 19:18
  • "Unit-tesing is about automation" - Correct, however so is integration testing (Selenium/Webdriver/etc.). I don't think it's necessarily so cut and dry that unit tests are faster to implement than integration tests. A lot depends on approach, however if getting an effective unit test requires mocking out a dozen different services and calls made into each one, an integration test may well be faster to implement and simpler to maintain (though generally much slower to run, yes). Point is, a lot depends on context, and complexity of the code under test. – aroth Dec 20 '16 at 0:16
  • @anotherdave comment added – Walfrat Dec 20 '16 at 10:08
  • @aroth my point was the opposite, full unit test a code is something that take a lot of time and make the code very hard to change without having some unit test to change. Integration test is lighter. Of course you'd want unit test something very complex, but it's not because you unit tested that part, that you have to unit test everything. Yet again we see people searching for the silver bullet where he does not exists. – Walfrat Dec 20 '16 at 11:42
23

Why would you write unit-tests for controllers?

Because without knowing the context you can't say for sure if you need to test this or that. Here are some reasons, why you might want to test controllers:

  • controller may contain complex service wiring logic, which is error-prone. Services themselves might work fine it's the result you want to test and for some reason you considered not to introduce orchestration layer into your app
  • your controllers contain THE WHOLE bussiness logic of the application and controllers are actually all you CAN test (please don't pretent that all your life you worked with ideal codebases, there ARE such codebases, believe me)
  • your team consists of 99% geniuses and 1% of average people and you want to keep that 1% out of bugs in their salary
  • 2
    I would add: "You can't foresee who in the future is going to get rid of the project, and tests are part of the self-documented code" – Laiv Dec 19 '16 at 12:27
  • 4
    To the middle point, a project that was created without testing in mind may not be testable any other way than a controller test without mocks. I work with a C# team that has exactly such a project in their care, so they are writing controller tests until they can add the necessary structure (interfaces, etc.) to be able to to finer-grained testing. – Wayne Conrad Dec 19 '16 at 13:01
0

I completely agree with the OP.

A unit test for a controller is pointless. You test your controllers implicitly via regression tests (using Selenium for example).

You should TDD all the components/objects the controller uses and keep the controllers as thin as possible. Then everything is properly unit tested. What you want to be certain of is that everything works well together when performing web requests. That's regression testing.

  • Maybe so, but that isn't an answer to the question. In fact, it's an argument against the use of unit tests here. – JᴀʏMᴇᴇ Dec 23 '16 at 13:16
  • I think I answered the question "do you believe a test is needed for this and why?" – winkbrace Dec 23 '16 at 16:51
  • Yes, I think @winkbrace and I share the same thoughts on this. But I also believe it's a discussion about what you should unit test and not. I think people test too much and the "wrong" things. in my example, testing the controller gives very little value since it's so thin and hopefully has tests surrounding the services. All answers here are meaningful and has good points but it's not really possible to mark one as a correct answer. – frostings Dec 27 '16 at 8:45
  • Controller logic can be tested using automated integration tests, separate and distinct from unit tests for individual components. – KevBurnsJr Sep 17 '17 at 21:31
  • -1: A unit test for a controller could be pointless. Controllers are about transformation, but sometimes the transformation itself is complex and a developer may want to have it covered. I also think that unit-tests 1) are ultimately about validating an implementation, not necessarily validating high-level behavior, and 2) are supposed to be damn fast. Both qualities make unit-tests much more useful during implementation time; in other words, they are ultimately a developer's tool, and just incidentally a way to validate product quality. – rsenna Jun 14 '18 at 15:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.