Stub Method in Spring Spock (Groovy) not being executed - spring

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?

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).

Does Juint reset global variables for each test?

I have an integration test class like this (but more complex)
#ExtendWith(SpringExtension::class)
#WebMvcTest(Controller::class)
class ScheduleControllerTest(#Autowired val mockMvc: MockMvc) {
val obj = object {
var b = 2
}
#Test
fun a(){
obj.b = 1
assertEquals(obj.b, 1)
}
#Test
fun b(){
assertEquals(obj.b, 2)
}
}
and all tests in this class pass as if after each test obj is reset to its initial value. No #Before functions are used here, so what is happening?
By default JUnit creates a new test class instance for each test run (fields are initialized anew each time). You can modify this behavior by using the #TestInstance annotation.

Mockito mock CassandraOperation Slice method

I am using the Mockito framework to write the mock Junit test cases below is my Service class to test the Junit test code
public class UserService {
#Autowired
private CassandraOperations template
public UserDTO getUserDTO(String date, String pagingState) {
Select select = QueryBuilder.select().all()
.from("tbl_user");
select.where(QueryBuilder.eq(date, date));
select.setFetchSize(30);
if (pagingState != null) {
select.setPagingState(PagingState.fromString(pagingState));
}
Slice<UserDTO> usgerDTO = template.slice(select, UserDTO.class);
if(usgerDTO.hasNext()) {
}
return usgerDTO.get();
}
Test case Class is writted
#RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
#InjectMocks
private UserService service ;
#Mock
private CassandraOperations template;
#Mock
private UserDTO userDTO;
private String date= "2019-09";
#Test(expected = Exception.class)
public void test() {
Slice<UserDTO> userDTO= Mockito.mock(Slice.class);
Select select = Mockito.mock(Select.class);
Mockito.when(template.slice(select, UserDTO.class)).thenReturn(userDTO);
metricReportDTO = service.getUserDTO(date, null);
}
}
I am getting Null values on this line
Slice<UserDTO> usgerDTO = template.slice(select, UserDTO.class);
Can you please helm me how to test template.slice method
Note: I should not use the PowerMockito
Your code snippet doesn't make sense in that you call service.getMetricsReports(date, null) in your test but your UserService code example only has the method getUserDTO. Assuming that is just a typo then you need to use matchers to get the mock to work in your when.
Mockito.when(template.slice(any(Select.class), eq(UserDTO.class))).thenReturn(userDTO);
This means whenever the first param is a class of type Select and the second is equal to UserDTO.class then return the userDTO if those 2 params don't match those conditions it will return null.
You can also make it match the exact Select assuming it has an overridden equals method. In the case where you send a null pagingState then something like:
Select stubSelect = QueryBuilder.select().all()
.from("tbl_user");
stubSelect.where(QueryBuilder.eq(date, date));
stubSelect.setFetchSize(30);
Mockito.when(template.slice(eq(stubSelect), eq(UserDTO.class))).thenReturn(userDTO);

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

groovy spock mocking spring autowired beans

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

Resources