groovy spock mocking spring autowired beans - spring

I have bean:
#Service
public class EQueueBookingService {
#Autowired
public EQueueBookingClient eQueueBookingClient;
And I try to write some test for this bean EQueueBookingService using Spock.
https://code.google.com/p/spock/wiki/SpockBasics
My mock is
class EQueueBookingServiceTest extends Specification {
#Autowired
EQueueBookingService testedService;
EQueueBookingClient eQueueBookingClient = Mock(EQueueBookingClient);
def setup() {
testedService.eQueueBookingClient = eQueueBookingClient;
}
and test method:
...
setup:
CancelBookingResponse response = new CancelBookingResponse();
...
eQueueBookingClient.cancelBooking(_, _) >> response;
when:
def result = testedService.cancelBooking(request);
then:
result != null && result.bookId == bookId
Why eQueueBookingClient doesn't mock?
When I debug it: in test - I see Mock instance, when I go to method - I see real bean instance.
Thanks a lot!

I've found solution!
need implement setter for this client and use it in setup like:
private EQueueBookingClient eQueueBookingClient = Mock(EQueueBookingClient);
def setup() {
testedService.setBookingClient(eQueueBookingClient);
}
If define client in service as public and use = it doesn't work;
For example:
testedService.eQueueBookingClient = eQueueBookingClient;//mocked instance doesn't work

Related

spring junit test data preparrer class access repositories trough field

I have simple class annotated with #Component and injected repositories like
#Component
class TestsDataPreparer(
private val carRepository: CarRepository
) {
fun withCar(builder: Car.() -> Unit = {}): Car {
return carRepository.save(
Car(
name = builder.name!!
)
)
}
}
which is clear..
But i wonder if it would be ok to do something like this, or if it is considered as anti-pattern.
#Component
class TestsDataPreparer(
val carRepository: CarRepository
) {
fun withCar(builder: Car.() -> Unit = {}): Car {
return carRepository.save(
Car(
name = builder.name!!
)
)
}
}
#Test
fun testCar() {
testsDataPreparer.withCar{this.name="Super-cool-car!"}
assertThat(testsDataPreparer.carRepository.findAll()).hasSize(1)
}
So the question is if it is okay to not inject repository in test class itself, but reuse it from TestsDataPreparer class
Yes, making an originally private field public just for testing can be considered an antipattern. Instead, you can create a CarRepository instance and then pass it to TestsDataPreparer when you create it. But for unit testing, you don't actually need that, you can use a mock and verify that the correct method was called (CarRepository.save).

Spring Boot - test without spring context with Spock

I have a service class and method with signature:
#Service
public class FileService {
....
....
public Optional<FileDescr> upload(MultipartFile uploadFile){...}
public Resource downloadFile(int linkID){...}
}
And test file (Groovy):
import org.junit.experimental.categories.Category
import org.springframework.mock.web.MockMultipartFile
import spock.lang.Shared
import spock.lang.Specification
#Category(WithoutSpringContext)
class FileServiceTestWithoutSpringContext extends Specification{
#Shared
FileService fileService = Mock()
#Shared
MockMultipartFile mockMultipartFile = Mock()
def setupSpec(){
}
def setup(){
}
def clean(){
}
def cleanSpec(){
}
def "upload file"(){
given:
fileService.upload(mockMultipartFile) >> true
when:
def result = fileService.upload(mockMultipartFile)
then:
result==true
}
def "download file if exists"(){
given:
fileService.downloadFile(1) >> true
when:
def result = fileService.downloadFile(1)
then:
result==true
}
}
I would like to test method with Mock, without spring context. How should I do it ? Now, the result variable return null.
I would like to set the return value of the method.
You can't annotate mocks with #Shared and there is no sense in it. #Shared is for other purposes:
Sometimes you need to share an object between feature methods. For example, the object might be very expensive to create, or you might want your feature methods to interact with each other. To achieve this, declare a #Shared field.
And further:
...mock objects should not be stored in static or #Shared fields.
Just remove #Shared and the spec will work just fine

Stub Method in Spring Spock (Groovy) not being executed

I have the following unit test I am working on.
#ContextConfiguration(
loader = SpringApplicationContextLoader,
classes = ManagementApplication.class
)
#WebAppConfiguration
class CTest extends Specification {
#Autowired
ClRepository clRepository
#Autowired
CoService coService
#Autowired
ClService clService
#Autowired
UserRepository userRepository
#Autowired
TopicRepository topicRepository
#Autowired
BasicAuthService authService
TopicService topicService = Spy(TopicService){
createTopicForCo(_) >> null
}
def setup(){
}
def "Simple Test Create"() {
given:
def cl = ClRepository.findOne(1L)
def sess = new Co(active: true, title: "Testing", cl: cl)
topicService.createTopicForCo(sess) >> null
ReflectionTestUtils.setField(coService, "topicService",topicService);
when:
println "Testing creation of coaching session"
sess = coService.create(sess)
then:
def coachingSessions = coService.findAll()
println coachingSessions
coachingSessions.size() > 0
}
}
I see that a topicService Mock object is being created.
ReflectionTestUtils.setField changes the topicService within coService with the Mocked one.
However, when createTopicForCo is called from within the topicService reference contained coService, the original implementation is called instead of my createTopicForCo(_) >> null.
Any ideas?

How to wait for transactions to commit using Propagation REQUIRES_NEW

I want to integration test a service method that calls a method that uses #Transactional(propagation = Propagation.REQUIRES_NEW). However, assertions based on the inner (new) transaction fail.
class MyService {
#Transactional(propagation = Propagation.NESTED)
def method1() {
method2()
}
#Transactional(propagation = Propagation.REQUIRES_NEW)
def method2() {
// some code that will modify the DB
}
}
class MyServiceNonTransactionalIntegrationSpec extends IntegrationSpec {
static transactional = false
def myService = new MyService()
setup() {
// populate database here
}
cleanup() {
// teardown database here after tests complete
}
def method1() {
when: "we test the main method"
myService.method1()
then: "we should be able to see the result of method 1 and method 2"
// BUT: (!!!)
// assertions based on state of database fail, perhaps because new transaction
// wrapped around method 2 has not yet committed
}
}
How do I integration test method1()?
EDIT:
In an attempt to work around the proxy issue, I've tried the following, but still can't get it to work:
class MyService {
def myService2
#Transactional(propagation = Propagation.NESTED)
def method1() {
myService2.method2()
}
}
class MyService2 {
#Transactional(propagation = Propagation.REQUIRES_NEW)
def method2() {
// some code that will modify the DB
}
}
class MyServiceNonTransactionalIntegrationSpec extends IntegrationSpec {
static transactional = false
def myService = new MyService()
def myService2 = new MyService2()
setup() {
myService.myService2 = myService2
// populate database here
}
// rest as before
}
It's only a self-invoking problem if you're using org.springframework.transaction.annotation.Transactional - you should be using #grails.transaction.Transactional instead which has the same configuration options but uses AST transforms instead of runtime proxies to avoid the issue of not calling the proxied method. When using the Grails annotation each method is rewritten to simulate creating a proxy for each one, wrapping the code in a transaction template that's configured based on the annotation settings for that method (either explicit on the method, or inferred from a class-scope annotation).
But your tests are broken because you're using new to create the services. Always use dependency injection in integration tests so you get the configured Spring bean, not just a new uninitialized POGO. To do this, add the same property syntax you would outside of your tests:
def myService
def myService2
and remove unnecessary wiring code (e.g. myService.myService2 = myService2) that Spring does for you.
You've faced self-invoking. Look here: Spring - #Transactional - What happens in background? or Spring #Transactional Annotation : Self Invocation
Here is excerption from one of my classes:
#Service("authzService")
public class AuthorizationService implements IAuthorizationService {
#Resource(name="authzService")
private IAuthorizationService self;
I use this private member for self invoke methods with #Cached annotation.

How to initialise/wire beans in Grails Spock unit tests?

I'm wanting to test a Grails controller that contains a bean (I'll move it to a Service when I get it working, but I just want to keep it simple now).
//resources.groovy
beans {
myBean(com.me.MyBean)
}
// MyBean.java
// this needs to be in java as it is playing with spring-data-neo4j
package com.me;
public class MyBean {
String show() {
return "Hello";
}
}
// TestController.groovy
package com.me
import com.me.MyBean
class TestController {
def myBean
def index() {
render myBean.show()
}
}
// TestControllerSpec.groovy
package com.me
import grails.test.mixin.TestFor
import spock.lang.Specification
import com.me.*
#TestFor(TestController)
class TestControllerSpec extends Specification {
def myBean
def setup() {
defineBeans {
myBean(com.me.MyBean) {bean->
bean.autowire = true
}
}
}
def cleanup() {
}
def "show() returns Hello"() {
when:
def rc = controller.myBean.show()
def rc2 = myBean.show()
then:
rc == "Hello"
rc2 == "Hello"
}
}
Within TestControllerSpec, myBean is null. controller.myBean is also null. I think this is because Spring is not picking the bean up and wiring it in. I gather that in unit tests not all spring beans are available, but what do I need to do to get controller.myBean to be instantiated and wired up correctly?
You must be mocking the myBean as below
def myBean = Mock(MyBean)
or
MyBean myBean = Mock()
and then stub out method for your need if required as below:
myBean.show >> "test data"
and then assign it to controller object which is already mocked for you.
controller.myBean = myBean
and there you go.
Or optionally you can stub out myBean and give stubbed implementations. For example,
MyBean myBean = Stub(){
show() >> {return "sample text"}
}
controller.myBean = myBean
The reason for doing this is we are not testing the integration of application entities like controller, views or domain but we are testing a single unit i.e. a method and hence we should be just testing it and for integration we should be using integration test cases which would be similar in everything except you won't require any mocking in normal scenarios.
Edit:
found another useful feature to mock services or beans using defineBeans closure as below:
defineBeans {
adapter(Adapter)
helperService(HelperService)
}
This will allow beans to be accessed from grailsApplication.
Hope it helps.

Resources