Integration and unit tests in large Grails project

后端 未结 2 1315
暗喜
暗喜 2021-01-31 06:14

It is usually more complicated to write unit tests due to having to deal with mock objects than integration tests in a large Grails project. This article even suggests we can ev

2条回答
  •  自闭症患者
    2021-01-31 06:51

    I always write my tests as unit tests if possible. I do this because:

    • unit tests execute quicker
    • I prefer to test each component in isolation, rather than testing all the components integrated together, because this makes it easier to identify the source of an error
    • the unit testing environment is simpler (e.g. no Spring application context), so there are fewer potential sources of failure that are unrelated to the test being performed

    An example of where I would write an integration test is if I want to test a Spring bean that I've defined in resources.groovy. Although I could instantiate the class and test it directly, my test would then need to know the current implementation class of that bean (which might change).

    In the long-run I think it's actually more complicated to write integration tests, because the cost of maintaining them over time is higher than unit tests. Groovy/Grails has excellent support for mocking/stubbing, so the cost of mocking dependencies in unit tests is relatively low. Here's a real-world example from one of my unit tests where I:

    • mock the messageSource Spring bean that would normally only be available in an integration test
    • mock two command classes such that I can call the validate() method, inspect the .errors property, etc.

    class MyUnitTests extends GrailsUnitTestCase {
    
        MessageSource messageSource
    
        protected void setUp() {
    
            super.setUp()
            // mockForConstraintsTests is a method provided by GrailsUnitTestCase
            [Complex, CategoryCommand].each {mockForConstraintsTests(it)}
    
            // 'mockMessage' will be returned by every method call on messageSource
            messageSource = {Object[] args -> "mockMessage"} as MessageSource
        }
    }
    

提交回复
热议问题