Spock How to mock Autowired class' function call within a method

主宰稳场 提交于 2019-12-10 10:45:28

问题


I have a class that I want to test in that looks like this: package com.something;

import org.springframework.beans.factory.annotation.Autowired;
public class ClassToTest implements InterfaceToTest{

  @Autowired
  AnotherService serviceA;

  @Override
  public List<String> methodToTest(List<String> randomVar){
    ...
    String stringA = serviceA.someFunction(randomVar);
    ...
  }
}

How can I mock the results from the call to serviceA.someFunction(randomVar) to return any String of my choice when testing with spock?

package com.something;
import spock.lang.Shared
import spock.lang.Specification
class TestClass extends Specification{
  @Shared InterfaceToTest classToTest = new ClassToTest()

  static doWithSpring = {
    serviceA(AnotherService)
  }

  def "tests-part-1"(){
    when: "something"
    ...
    then: "expect this"
    ...
  }
}

I dont know where to go from here. My IDE shows errors with the doWithSpring code I added to the testing class. Any ideas on how to deal with this?


回答1:


I would suggest thinking of it from more of a unit testing perspective. You want to mock out the spring framework stuff and just make sure that you're testing your logic. This is very easy to do with Spock.

ClassToTest myClass = new ClassToTest(serviceA: Mock(AnotherService))

def "test my method"() {
  when:
  myClass.methodToTest([])

  then:
  1 * myClass.serviceA.someFunction([]) >> 'A string'
}

From here, you can look at data driving it or using a >>> and passing a list of the different strings that you'd like to return.




回答2:


A simple solution to enable unit testing would be to alter ClassToTest to have a constructor which sets the serviceA field like this:

import org.springframework.beans.factory.annotation.Autowired;
public class ClassToTest implements InterfaceToTest{

private AnotherService serviceA;

@Autowired
public ClassToTest(final AnotherService serviceA){
   this.serviceA = serviceA;
}

@Override
public List<String> methodToTest(List<String> randomVar){
...
String stringA = serviceA.someFunction(randomVar);
...
}
}

Then in your spock unit test you can provide a mock in the constructor:

class TestClass extends Specification{
 def mockServiceA = Mock(AnotherService)
 @Shared InterfaceToTest classToTest = new ClassToTest(mockServiceA)

And in each test case you can mock in the usual spock way:

1 * mockServiceA.someFunction(_) >> 'A string'



回答3:


If you are unit testing, then do what @rockympls suggests.

If you are integration/component testing, then include spock-spring dependency and look at the test examples from the Spock guys. Furthermore, if you are using Spring Boot 1.4+, you can do something like:

@SpringBootTest(classes = Application)
@ContextConfiguration
class SomeIntegrationTest extends Specification {

    @Autowired
    SomeService someService

    def 'some test case'() {
        ...
    }
}

For more on the Spring Boot testing stuff see this.



来源:https://stackoverflow.com/questions/38878338/spock-how-to-mock-autowired-class-function-call-within-a-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!