djcrankypants / spock

Automatically exported from code.google.com/p/spock
0 stars 0 forks source link

Spring MVC Testing in 3.2 version doesn't work with Spock #299

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago

My Test class is 
@RunWith(SpringJUnit4ClassRunner)
@WebAppConfiguration
@ContextConfiguration(classes=[MvcConfig,TestServiceConfig])
class HelloSpec {
 @Autowired
    CacheService cacheService

 @Test
    void 'check return contentType'() {

        setup:

        cacheService.sayHi(_) >> ["Hello"]

        when:
        def t = this.perform('/hello')

        then:
        t.andDo(print())
    }
}

my controller is this 
@Controller
class HelloController {
    @Autowired
    CacheService cacheService

    @RequestMapping(value = "/hello", method = GET, consumes = MEDIA_TYPE, produces = MEDIA_TYPE)
    @ResponseStatus(value = HttpStatus.OK)
    @ResponseBody
    public def getHostel() {
       cacheService.sayHi()
    }

When I run this test,  cacheService instance in the controller returns null eve 
though I set "Hello" in the test

What version of Spock and Groovy are you using?
groovy 2.1 and spock 0.7-groovy-2.0

Please provide any additional information below. You can also assign
labels.

I think Specification class requires to be run with RunWith("Sputnik") whereas 
MVC Test requires RunWith("SpringJUnit4ClassRunner")

Original issue reported on code.google.com by ramazan....@gmail.com on 18 Feb 2013 at 3:31

GoogleCodeExporter commented 8 years ago
Your `HelloSpec` class isn't a Spock specification. Remove the `@RunWith` 
annotation, remove `@Test`, extend class `spock.lang.Specification`, and make 
sure that the `spock-spring` Jar is on the runtime class path. Still, you 
cannot use Spock's mocking support for mocking an injected service (if that's 
what you are trying to do).

Original comment by pnied...@gmail.com on 18 Feb 2013 at 3:41

GoogleCodeExporter commented 8 years ago
Sorry it was my mistake.. I was simplifying my test case 

import org.junit.Before
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.MediaType
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
import org.springframework.test.context.web.WebAppConfiguration
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.ResultActions
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import org.springframework.web.context.WebApplicationContext

@RunWith(SpringJUnit4ClassRunner)
@WebAppConfiguration
@ContextConfiguration(classes=[MvcConfig,TestServiceConfig])
class HelloSpec extends Specification{

    @Autowired
    private WebApplicationContext wac;
  private MockMvc mockMvc;

    @Before
    void createMockMvc() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();

    }

    protected ResultActions perform(String url, String mediaType) {
        this.mockMvc.perform(get(url).contentType(MediaType.valueOf(mediaType)))
    }

 @Test
    void 'check return contentType'() {

        setup:

        cacheService.sayHi(_) >> ["Hello"]

        when:
        def t = this.perform('/hello')

        then:
        t.andDo(print())
    }

}

As you can see here , we have to use both JUnit and Sputnik at the same time.

Original comment by ramazan....@gmail.com on 18 Feb 2013 at 3:56

GoogleCodeExporter commented 8 years ago
as an extra note  There is no problem with integration with Spring but the 
problem is new Spring MVC Test in 3.2 version

Original comment by ramazan....@gmail.com on 18 Feb 2013 at 3:58

GoogleCodeExporter commented 8 years ago
Again, as soon as you add `@RunWith(SpringJUnit4ClassRunner)`, Spock is out of 
the game, and ISN"T USED AT ALL. If you do what I said, it should work, except 
that you can't simply mock or stub an injected service (not sure where you got 
that idea from).

Original comment by pnied...@gmail.com on 18 Feb 2013 at 4:05

GoogleCodeExporter commented 8 years ago
Hi
Your comments really helped me to understand what is going on here. I now
removed SpringJunit4ClassRunner..

Again I forgot to add some lines of code here

@WebAppConfiguration
@ContextConfiguration(classes=[MvcConfig,TestServiceConfig])

What i am testing here only Spring MVC layer classes with mocking injected
service classes . It is my idea and it works. Why do you see it is an
problem?

When I remove SpringJunit4ClassRunner , @WebAppConfiguration seems doens't
work now.

How i can I understand spock-spring works as expected ?

Original comment by ramazan....@gmail.com on 18 Feb 2013 at 4:14

GoogleCodeExporter commented 8 years ago
here is TesServiceConfig

@Configuration
class TestServiceConfig extends Specification {

    @Bean
    CacheService cacheService() {
        Mock(CacheService)
    }
}

We are mocking CacheService here

On Mon, Feb 18, 2013 at 4:14 PM, Ramazan Varlıklı <
ramazan.varlikli@gmail.com> wrote:

Original comment by ramazan....@gmail.com on 18 Feb 2013 at 4:22

GoogleCodeExporter commented 8 years ago
I see. That might work, as long as you run the test class with Spock rather 
than JUnit. :-)

Are you absolutely sure that you have `spock-spring` on the test class path?

Original comment by pnied...@gmail.com on 18 Feb 2013 at 4:29

GoogleCodeExporter commented 8 years ago
Yes
Spring Beans injected normally so there shouldn't be a problem with
spock-spring.

Now I removed the SpringJunitRunner and come again the same problem. I am
trying to set a return value for mocked method but it returns null

Original comment by ramazan....@gmail.com on 18 Feb 2013 at 4:33

GoogleCodeExporter commented 8 years ago
Another issue might be that

My HelloSpec extends Specification so that WebApplicationContext can set
the injected beans into controller classes.

TestServicesConfig also extends Specification class so that I can mock
original Services classes .

I don't know how spock handles interactions with mock but having 2
Specification classes might cause the problem .

I

On Mon, Feb 18, 2013 at 4:33 PM, Ramazan Varlıklı <
ramazan.varlikli@gmail.com> wrote:

Original comment by ramazan....@gmail.com on 18 Feb 2013 at 4:41

GoogleCodeExporter commented 8 years ago
You are right, that won't work because the mock gets registered with the wrong 
spec. I think you'll have to implement a stub by hand.

Original comment by pnied...@gmail.com on 18 Feb 2013 at 5:00

GoogleCodeExporter commented 8 years ago
If I need to create my own stub , then there is not so much benefit to use
spock ?

Original comment by ramazan....@gmail.com on 18 Feb 2013 at 5:04

GoogleCodeExporter commented 8 years ago
Hi Peter

I need to define a test strategy in my project soon. My understanding so far is 
that I can't use spock with Spring MVC Test framework. either spock without 
spring mvc test or mockito(or any other mocking framework) with Spring MVC Test.

If it is something could be fixed in short term , i can wait for it to be able 
to use spock as I use it as main mocking framework 

Original comment by ramazan....@gmail.com on 20 Feb 2013 at 5:38

GoogleCodeExporter commented 8 years ago
You can absolutely use Spock with the Spring MVC test framework. The only thing 
that you can't do is to wire up a Spock mock as a Spring bean in an application 
context. Not sure if that's a good idea in the first place.

Of course, Spock offers many other advantages besides its mocking framework, 
and you can combine it with other mocking frameworks (e.g. Mockito) where 
needed.

PS: http://forum.spockframework.org is a better place for such discussions.

Original comment by pnied...@gmail.com on 21 Feb 2013 at 5:33

GoogleCodeExporter commented 8 years ago
If you'd like to see support for detached mock objects, please open a new issue.

Original comment by pnied...@gmail.com on 15 Mar 2013 at 10:57