spock framework override method in test class - java

Tested class:
public class ClassForTest {
public String hello(){
return "hello " + getClassName();
}
public String getClassName(){
return ClassForTest.class.getName();
}
}
Spock class:
class ClassForSpockTest extends Specification{
def setupSpec(){
ClassForTest.metaClass.getClassName={"ClassForSpockTest"}
}
def "override test"(){
setup:
ClassForTest cft = new ClassForTest()
expect:
cft.getClassName() == "ClassForSpockTest"
}
def "mock test"(){
setup:
ClassForTest cft = new ClassForTest()
expect:
cft.hello() == "hello ClassForSpockTest"
}
}
override test test is passed!
Mock test is crashing, cft.hello() return "hello ClassForTest"

You can't use the metaclass to override a method call in a Java class from another method in that class. This is a limitation of spock, Java, and groovy. In this case, you have to use other mocking techniques. For example, you can use subclassing:
setup:
ClassForTest cft = new ClassForTest() {
String getClassName() {"ClassForSpockTest"}
}

Related

Using Spock/Groovy to test a Java method that extends HashMap - how to mock HashMap get method?

In our codebase, we use a specific class map which stores the results for authorization requests including whether or not someone has the auth to get in.
Currently writing some unit tests (a thing I have little practice on) that contains this, a modified version of our code for you to look at:
public class TestResultMap extends HashMap<String, TestResult> {
private static final long serial = -1234567890L;
public boolean isAuthorized(String resource) {
TestResult result = get(resource);
if (result == null) {
throw new RunExcept("Authorization not calculated");
}
return result.isAuthorized();
}
}
When testing the isAuthorized() in the groovy file I had made, I've noticed that no matter how I have it arranged, I can not get it to instantiate TestResult result = get(resource) to be anything other than null. isAuthorized() calls upon an enum method in another class that contains the possibilities, but otherwise just returns a boolean.
That's tangential to the point, though. Is there an efficient way to mock this or force get(resource) to output something not null? Alternatively, can I directly set result to a particular value?
Thanks for any help. Incredibly new to this whole process and documentation has been tricky.
I am showing you
how to stub the result of TestResult.isAuthorized to always return true or false,
how to use a spy on a real TestResultMap instance in order to stub the result of get(_) with the rest of the class behaving normally (partial mocking),
how to test your class without using any mocks, because if the methods used in the test are not doing anything expensive, mocking might not be necessary at all. Or maybe you want to also have an integration test in addition to the unit test with mocked dependencies.
Classes under test:
package de.scrum_master.stackoverflow.q70149644;
public class TestResult {
private String result;
public TestResult(String result) {
this.result = result;
}
public boolean isAuthorized() {
return !result.toLowerCase().matches(".*(forbidden|blocked|unauthorized|denied).*");
}
#Override
public String toString() {
return "TestResult(result='" + result + "')";
}
}
package de.scrum_master.stackoverflow.q70149644;
import java.util.HashMap;
public class TestResultMap extends HashMap<String, TestResult> {
private static final long serial = -1234567890L;
public boolean isAuthorized(String resource) {
TestResult result = get(resource);
if (result == null) {
throw new RuntimeException("Authorization not calculated");
}
return result.isAuthorized();
}
}
Spock specification:
package de.scrum_master.stackoverflow.q70149644
import spock.lang.Specification
class TestResultMapTest extends Specification {
def "resource is authorized"() {
given:
TestResultMap map = new TestResultMap()
TestResult testResult = Stub() {
isAuthorized() >> true
}
map.put("resource", testResult)
expect:
map.isAuthorized("resource")
}
def "resource is unauthorized"() {
given:
TestResultMap map = new TestResultMap()
TestResult testResult = Stub() {
isAuthorized() >> false
}
map.put("resource", testResult)
expect:
!map.isAuthorized("resource")
}
def "resource not found"() {
given:
TestResultMap map = Spy() {
get(_) >> null
}
when:
map.isAuthorized("resource")
then:
def rte = thrown RuntimeException
rte.message == "Authorization not calculated"
}
def "test without mocks"() {
given:
TestResultMap map = new TestResultMap()
map.put("OK", new TestResult("Hello world"))
map.put("not OK", new TestResult("Access denied"))
expect:
map.isAuthorized("OK")
!map.isAuthorized("not OK")
when:
map.isAuthorized("foo")
then:
def rte = thrown RuntimeException
rte.message == "Authorization not calculated"
}
}

Fields don't match but the test was still passed. [Mockito Test]

I have the following test set up. I don't understand how the test is passing successfully since the user is set to "Dummy."
#RunWith(MockitoJUnitRunner.class)
public class TodoServiceAbstractImplTest
{
#InjectMocks
TodoServiceAbstractImpl todoServiceAbstractImpl = new TodoServiceAbstractImpl();
#Mock
SomeRandomClass someRandomClass;
#Mock
TodoServiceAbstract todoServiceAbstract;
#Test
public void testRetrieveTodo_usingAMock(){
todoServiceAbstractImpl.setUser("Dummy"); //Set the user to be "Dummy" already
assertEquals(null,todoServiceAbstractImpl.getUser()); //Why is the user is still null?
}
}
Here are the relevant classes. I created them to test Mockito as I am still learning testing in Spring Boot.
Definition of the SomeRandomClass:
public class SomeRandomClass{
private String field;
public SomeRandomClass(){
}
public SomeRandomClass(String field){
setRandom(field);
}
public void setRandom(String field){
this.field = field;
}
public String getRandom(){
return field;
}
}
Definition of the Abstract class:
public abstract class TodoServiceAbstract {
#Autowired
private SomeRandomClass RandomUser;
public TodoServiceAbstract(){
//RandomUser = new SomeRandomClass();
}
public void setUser(String user){
this.RandomUser.setRandom(user);
}
public String getUser(){
return RandomUser.getRandom();
}
public abstract List<String> retrieveTodos(String user);
}
Definition of the Abstract Implementation
public class TodoServiceAbstractImpl extends TodoServiceAbstract{
public List<String> retrieveTodos(String user){
if(user == getUser()){
return Arrays.asList("item 1", "item 2",
"item 3");
}
return Arrays.asList("Random item");
}
}
Tom answered in the comments:
Why do you expect something else than null? SomeRandomClass is mocked so it obviously doesn't actually set anything when calling setUser. And why should it? That's the point of a mock.
Remember that mocked implementations are not real, and in particular unstubbed calls will return dummy values such as null, 0, or an empty string.
In addition to what Tom already said in the comments, this test is testing your mocks, rather than your actual implementation. Since you mocked SomeRandomClass, your tests should verify if that method is being called. In this case you should test if SomeRandomClass.setRandom() is called when you call setUser() and likewise, you should test if SomeRandomClass.getRandom() is called when you call getUser().
For example:
#Test
public void getUser_shouldUseGetRandom() {
when(someRandomClass.getRandom()).thenReturn("data");
assertEquals("data", todoServiceAbstractImpl.getUser());
}
To test setUser() you can do something like:
#Test
public void setUser_shouldUseSetRandom() {
todoServiceAbstractImpl.setUser("data");
verify(someRandomClass).setRandom("data");
}
By mocking/stubbing you can write proper unit tests for TodoServiceAbstractImpl without having to take the behaviour of SomeRandomClass.

How to mock methods/functions provided by Traits in Groovy

Here's an example:
trait Sender {
def send(String msg){
// do something
}
}
class Service implements Sender {
def myMethod1(){
send('Foo')
myMethod2()
}
def myMethod2(){
}
}
I am trying to test the Service class. However, I would like to stub/mock the calls to the methods provided by the trait (send)?
I have tried several different ways to stub/mock the method send, with no success:
// 1
Service.metaclass.send = { String s -> // do nothing }
// 2
def service = new MyService()
service.metaClass.send = { String s -> // do nothing }
// 3
StubFor serviceStub = new StubFor(Service.class)
serviceStub.demand.send { String s -> // do nothing }
//
trait MockedSender {
def send(String msg) { // do nothing }
}
def service = new Service() as MockedSender
These are just some of the things I tried. I even tried using Mock frameworks like Mockito. Unfortunately, nothing seems to work. Any suggestions???
Try using Spy from Spock framework!
Like this:
trait Sender {
def send(String msg){
println msg
}
}
class Service implements Sender {
def myMethod1(){
send('Foo')
myMethod2()
}
def myMethod2(){
println 'real implementation'
}
}
class UnitTest extends Specification {
def "Testing spy on real object"() {
given:
Service service = Spy(Service)
when:
service.myMethod1()
then: "service.send('Foo') should be called once and should print 'mocked' and 'real implementation' on console"
1 * service.send('Foo') >> { println 'mocked' }
}
}

Stub void method in Spock which populate

How can I stub/mock a void method which populates some objects that would be used later.
class RequestHelper{
public void populateOrderRequestBody(String product,String quantity,String profile, OrderType orderType){
orderType.setProduct(product);
orderType.setQuantity(Integer.parseInt(quantity));
orderType.setUser(profile.getUserId());
} }
class ServiceClient{
RequestHelper rh;
public void docall(Order order){
OrderType orderType = FACTORY.CreateOrderType;
rh.populateOrderRequestBody(order.getProduct(),order.getQuantity(),order.getProfile(),orderType);
/**
* some other code
**/
}
public setRequestHelper(RequestHelper rh){
this.rh=rh;
}
public RequestHelper getRequestHelper(){
return this.rh;
}}
Now I want to test ServiceClient class which call RequestHelper to populate orderType object. How to stub the method of RequestHelper class.
In this particular case if no verification will be done to rh filed you just need a plain Stub - just to ensure no NullPointerException is thrown when testing the docall method. Mock will also be sufficient however is more advanced object and using it here is pointless. When it comes to Spy it's used to verify invocations on a real (in terms of not being mocked) object. Have a look at the example below - runs smoothly just with Stub:
#Grab('org.spockframework:spock-core:1.0-groovy-2.4')
#Grab('cglib:cglib-nodep:3.1')
import spock.lang.*
class Test extends Specification {
def 'spec'() {
given:
def service = new ServiceClient()
service.rh = Mock(RequestHelper)
when:
service.doCall(new Order())
then:
noExceptionThrown()
}
}
class Order {
String product
String quantity
String profile
}
class OrderType { }
class FACTORY {
static OrderType CreateOrderType = new OrderType()
}
class RequestHelper {
public void populateOrderRequestBody(String product, String quantity, String profile, OrderType orderType) {
orderType.setProduct(product);
orderType.setQuantity(Integer.parseInt(quantity));
orderType.setUser(profile.getUserId());
}
}
class ServiceClient {
RequestHelper rh;
public void doCall(Order order) {
OrderType orderType = FACTORY.CreateOrderType;
rh.populateOrderRequestBody(order.getProduct(), order.getQuantity(), order.getProfile(), orderType);
}
public setRequestHelper(RequestHelper rh){
this.rh=rh;
}
public RequestHelper getRequestHelper(){
return this.rh;
}
}
Very similar to Opal's answer but using a mock order..
class Test extends Specification {
def 'spec'() {
given:
def service = new ServiceClient()
def order = Mock(Order)
order.getProduct() >> 'product1'
order.getProfile() >> 'profile1'
order.getQuantity() >> 3
service.rh = Mock(RequestHelper)
when:
service.doCall(order)
then:
noExceptionThrown()
1 * rh.populateOrderRequestBody('product1',3,'profile1',FACTORY.CreateOrderType)
}
}
Note that this only works if the CreateOrderType.equals() will return true

Mocking Util class's static method using gmock

class SomeService{
public String getValue(){
return SomeUtil.generateValue();
}
}
class SomeUtil{
public static String generateValue() {
return "yahoo";
}
}
I want to unit test the SomeService.getValue method.
I am trying the following:
#Test
void "getValue should return whatever util gives"(){
def mockSomeUtil = mock(SomeUtil)
mockSomeUtil.static.generateValue().returns("blah")
play {
Assert.assertEquals(someService.getValue(), "blah")
}
}
But it fails as the util method isn't actually getting mocked.
Question:
How can I unit test my service method?
I made a quick test and it is working without a hassle:
#Grapes([
#Grab(group='org.gmock', module='gmock', version='0.8.3'),
#Grab(group='junit', module='junit', version='4.12')
])
import org.gmock.*
import org.junit.*
import org.junit.runner.*
class SomeService {
public String getValue(){
return SomeUtil.generateValue()
}
}
class SomeUtil {
public static String generateValue() {
return "yahoo"
}
}
#WithGMock
class DemoTest {
def someService = new SomeService()
#Test
void "getValue should return whatever util gives"() {
def mockSomeUtil = mock(SomeUtil)
mockSomeUtil.static.generateValue().returns("blah")
play {
Assert.assertEquals(someService.getValue(), "blah")
}
}
}
def result = JUnitCore.runClasses(DemoTest.class)
assert result.failures.size() == 0
If you need to invoke the service several times, you may need a stub, i.e.:
mockSomeUtil.static.generateValue().returns("blah").stub()

Categories

Resources