I'm new to groovy and I'm trying to use Spock to do some integration tests.
I have a Java class FunctionalTestCase which I used as a framework before to do my tests.
For Spock, I'm still using this FunctionalTestCase from a groovy class. Most of the things worked without problems, but I have the following scenario:
In FunctionalTestCase I have something similar:
protected static void doSomething(#Nullable Object nullableObject)
{
SomeInterface<InstrumentQuotationDataImage> marketDataSnapshot = new SomeInterface<InstrumentQuotationDataImage>()
{
#Override
public InstrumentQuotationDataImage getData()
{
InstrumentQuotationDataImage instrumentQuotationData = new InstrumentQuotationDataImageImpl();
if (nullableObject != null)
{
instrumentQuotationData.setDataRecord(nullableObject);
}
return instrumentQuotationData;
}
};
marketData.getQuotationService().pushQuotation(marketDataSnapshot);
}
This method is called once at setup with a non null parameter, and pushes an object into a Service (this can be seen at the end of the code).
When I later want to call SomeInterface#getData from the object retrieved from that QuotationService, instead of nullableObject to be null it throws groovy.lang.MissingPropertyException.
Any idea why this happens from groovy? Using it from java everything works ok and the objects are null.
Related
I have a code that I cannot correctly cover with tests.
I am using the Mockito library.
And I had difficulty at the moment of starting the test.
Below is the test code:
#Test
public void testLoadCar() {
when(remoteService.loadData()).thenReturn(new DataResult<DataCar>("", "", new DataCar()));
when(dataResult.hasError()).thenReturn(true);
when(dataResult.response.hasHeaders()).thenReturn(true);
requestNetwork = new RequestNetwork(remoteService);
Response<DataCar> response = requestNetwork.load(request);
}
These are objects in the test class: remoteService, dataResult, request.
I am concerned about the moment where I am trying to implement the when method:
when(dataResult.response.hasHeaders()).thenReturn(true);
I would like to know if such a recording will work.
If it doesn't work, then how can we handle this moment:
protected Response createResponse(DataResult<T> dataResult) {
if (dataResult.hasError() || !dataResult.response.hasHeaders()) {
return dataResult.getErrorMessage());
} else {
return Response.data(dataResult.value);
}
}
This is a method on the system under test (SUT) that has a createResponse() method. This method contains a call to the mock method of the DataResult object.
To implement dataResult.hasError () I got it:
when (dataResult.hasError ()). thenReturn (true);
Then with! DataResult.response.hasHeaders () I have a problem. Since I don't understand how to substitute the value I need.
Not all objects that your object under test interacts with need to be mocks.
Remember that you can use POJOs as well.
DataResult looks like a perfect candidate for a POJO.
You gain nothing by using a mock objet if you can create a POJO with desired state and behaviour.
Looking at the posted code, it looks like it is easy to create:
new DataResult<DataCar>("", "", new DataCar())
On top of that:
Your code looks suspicious to me.
when stubbing remoteService.loadData() you create a new instance of DataResult
subsequently, you stub some calls on dataResult, which is not an object returned from remoteService.loadData()
And to answer original post:
You can set fields on mocks (directly if access modifiers allow it, or via reflection otherwise). Note that this is highly not-idiomatic and surprising use of mocks.
class A {
B b;
}
class B {
boolean hasHeaders() {
return true;
}
}
#ExtendWith(MockitoExtension.class)
public class AAATest {
#Mock
A aMock;
#Mock
B bMock;
#BeforeEach
void setupMocks() {
aMock.b = bMock;
}
#Test
void testFieldInMockIsInitialized() {
Assertions.assertEquals(bMock, aMock.b);
}
}
How to mock methods with void return type?
I implemented an observer pattern but I can't mock it with Mockito because I don't know how.
And I tried to find an example on the Internet but didn't succeed.
My class looks like this:
public class World {
List<Listener> listeners;
void addListener(Listener item) {
listeners.add(item);
}
void doAction(Action goal,Object obj) {
setState("i received");
goal.doAction(obj);
setState("i finished");
}
private string state;
//setter getter state
}
public class WorldTest implements Listener {
#Test public void word{
World w= mock(World.class);
w.addListener(this);
...
...
}
}
interface Listener {
void doAction();
}
The system is not triggered with mock.
I want to show the above-mentioned system state. And make assertions according to them.
Take a look at the Mockito API docs. As the linked document mentions (Point # 12) you can use any of the doThrow(),doAnswer(),doNothing(),doReturn() family of methods from Mockito framework to mock void methods.
For example,
Mockito.doThrow(new Exception()).when(instance).methodName();
or if you want to combine it with follow-up behavior,
Mockito.doThrow(new Exception()).doNothing().when(instance).methodName();
Presuming that you are looking at mocking the setter setState(String s) in the class World below is the code uses doAnswer method to mock the setState.
World mockWorld = mock(World.class);
doAnswer(new Answer<Void>() {
public Void answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
System.out.println("called with arguments: " + Arrays.toString(args));
return null;
}
}).when(mockWorld).setState(anyString());
I think I've found a simpler answer to that question, to call the real method for just one method (even if it has a void return) you can do this:
Mockito.doCallRealMethod().when(<objectInstance>).<method>();
<objectInstance>.<method>();
Or, you could call the real method for all methods of that class, doing this:
<Object> <objectInstance> = mock(<Object>.class, Mockito.CALLS_REAL_METHODS);
Adding to what #sateesh said, when you just want to mock a void method in order to prevent the test from calling it, you could use a Spy this way:
World world = new World();
World spy = Mockito.spy(world);
Mockito.doNothing().when(spy).methodToMock();
When you want to run your test, make sure you call the method in test on the spy object and not on the world object. For example:
assertEquals(0, spy.methodToTestThatShouldReturnZero());
The solution of so-called problem is to use a spy Mockito.spy(...) instead of a mock Mockito.mock(..).
Spy enables us to partial mocking. Mockito is good at this matter. Because you have class which is not complete, in this way you mock some required place in this class.
First of all: you should always import mockito static, this way the code will be much more readable (and intuitive):
import static org.mockito.Mockito.*;
For partial mocking and still keeping original functionality on the rest mockito offers "Spy".
You can use it as follows:
private World world = spy(new World());
To eliminate a method from being executed you could use something like this:
doNothing().when(someObject).someMethod(anyObject());
to give some custom behaviour to a method use "when" with an "thenReturn":
doReturn("something").when(this.world).someMethod(anyObject());
For more examples please find the excellent mockito samples in the doc.
How to mock void methods with mockito - there are two options:
doAnswer - If we want our mocked void method to do something (mock the behavior despite being void).
doThrow - Then there is Mockito.doThrow() if you want to throw an exception from the mocked void method.
Following is an example of how to use it (not an ideal usecase but just wanted to illustrate the basic usage).
#Test
public void testUpdate() {
doAnswer(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
if (arguments != null && arguments.length > 1 && arguments[0] != null && arguments[1] != null) {
Customer customer = (Customer) arguments[0];
String email = (String) arguments[1];
customer.setEmail(email);
}
return null;
}
}).when(daoMock).updateEmail(any(Customer.class), any(String.class));
// calling the method under test
Customer customer = service.changeEmail("old#test.com", "new#test.com");
//some asserts
assertThat(customer, is(notNullValue()));
assertThat(customer.getEmail(), is(equalTo("new#test.com")));
}
#Test(expected = RuntimeException.class)
public void testUpdate_throwsException() {
doThrow(RuntimeException.class).when(daoMock).updateEmail(any(Customer.class), any(String.class));
// calling the method under test
Customer customer = service.changeEmail("old#test.com", "new#test.com");
}
}
You could find more details on how to mock and test void methods with Mockito in my post How to mock with Mockito (A comprehensive guide with examples)
In Java 8 this can be made a little cleaner, assuming you have a static import for org.mockito.Mockito.doAnswer:
doAnswer(i -> {
// Do stuff with i.getArguments() here
return null;
}).when(*mock*).*method*(*methodArguments*);
The return null; is important and without it the compile will fail with some fairly obscure errors as it won't be able to find a suitable override for doAnswer.
For example an ExecutorService that just immediately executes any Runnable passed to execute() could be implemented using:
doAnswer(i -> {
((Runnable) i.getArguments()[0]).run();
return null;
}).when(executor).execute(any());
Adding another answer to the bunch (no pun intended)...
You do need to call the doAnswer method if you can't\don't want to use spy's. However, you don't necessarily need to roll your own Answer. There are several default implementations. Notably, CallsRealMethods.
In practice, it looks something like this:
doAnswer(new CallsRealMethods()).when(mock)
.voidMethod(any(SomeParamClass.class));
Or:
doAnswer(Answers.CALLS_REAL_METHODS.get()).when(mock)
.voidMethod(any(SomeParamClass.class));
I think your problems are due to your test structure. I've found it difficult to mix mocking with the traditional method of implementing interfaces in the test class (as you've done here).
If you implement the listener as a Mock you can then verify the interaction.
Listener listener = mock(Listener.class);
w.addListener(listener);
world.doAction(..);
verify(listener).doAction();
This should satisfy you that the 'World' is doing the right thing.
If you need to do some operations in the mocked void method, and you need to manipulate the argument that sent to void method; you can combine Mockito.doAnswer with ArgumentCaptor.capture method.
Let's say you have SpaceService that autowires a GalaxyService, which has a void method called someServiceMethod.
You want to write test for one of your method in SpaceService that calls GalaxyService's void method. Your planet is also generated inside SpaceService. So you don't have any chance to mock that.
Here is your sample SpaceService class that you want to write tests for.
class SpaceService {
#Autowired
private GalaxyService galaxyService;
public Date someCoolSpaceServiceMethod() {
// does something
Planet planet = new World();
galaxyService.someServiceMethod(planet); //Planet updated in this method.
return planet.getCurrentTime();
}
}
The GalaxyService.someServiceMethod method expects a planet argument. Does some stuff in the method. See :
GalaxyService {
public void someServiceMethod(Planet planet) {
//do fancy stuff here. about solar system etc.
planet.setTime(someCalculatedTime); // the thing that we want to test.
// some more stuff.
}
}
And you want to test this feature.
Here is an example :
ArgumentCaptor<World> worldCaptor = ArgumentCaptor.forClass(World.class);
Date testDate = new Date();
Mockito.doAnswer(mocked-> {
World capturedWorld = worldCaptor.getValue();
world.updateTime(testDate);
return null;
}).when(galaxyService.someServiceMethod(worldCaptor.capture());
Date result = spaceService.someCoolSpaceServiceMethod();
assertEquals(result, testDate);
In your example you should mock Listener item and use Mockito.verify to check interactions with it
I want to intercept all method calls for Script and any of its subtypes using MetaClasses preferably from Java but if needed I can do it from Groovy. I basically want to do something like this:
MetaClassImpl meta = new MetaClassImpl(Script.class) {
#Override
public final Object invokeMethod(Object obj, String method, Object[] args) {
if(method.equals("evaluate")) {
System.out.println("intercepted");
return run(shell, (String) args[0], "Evaluate");
} else {
return super.invokeMethod(obj, method, args);
}
}
};
The above works fine if I apply it to every instance of Script that I create but I'd like to apply it to the Script class and have it apply to all of its subtypes. Is there any way of doing this?
EDIT: What I'm attempting to do is replace evaluate with another method for all instances of Script and its subtypes. Either that or get evaluate to respect the ImportCustomizer set on the groovy shell the script is running inside of.
I have a class with a few methods advised through an input validation aspect (validates whether all input parameters are not-null/non-empty strings).
I am facing an issue while writing test case for them and want to verify if this is indeed a bad design issue.
Here's a very simplified version of my class:
public class A {
public String one(String word) {
// Some actions
String val = two(word2);
// Some more actions
}
protected String two(String word) {
// Some actions
}
}
Now while writing test cases for one() I use Mockito and want to mock calls to two(). So I use:
#Spy
A a;
#Test
void test() {
doReturn("Bye").when(A).two(Mockito.anyString());
a.one("hello");
// Some validations
}
This test fails as the: doReturn() line fails with input being empty for two().
Should I not mock two() or can I make this work somehow?
Edit:
Adding a more specific example related to the two methods being present in two different classes as requested:
Create a page through a WebService. This builds a putRequest, executes it and returns a response.
public class AUtility implements BaseUtility {
public Response create(Params params) {
try {
PutMethod putRequest = buildPUTRequest(params.getAttr1(), params.getAttr2());
return Utils.buildResponse(client.executeMethod(putRequest),
params.getAttr3(),
params.getAttr4());
} catch (Exception e) {
throw new AppException(e);
}
}
}
The put request marshals the data into a file to write it through the HttpClient
private PutMethod buildPUTRequest(final String url, final Object obj) throws IOException, JAXBException {
// Create a temp file to store the stream
File tempFile = File.createTempFile(APPLICATION_LABEL, XML_LABEL);
decoder.marshal(obj, tempFile);
// Build the put method
return putMethod;
}
XMLMarshaller
public interface XMLDecoder implement Decoder {
public void marshal(Object obj, File tempFile) throws IOException, JAXBException {
// Perform marshalling operations
}
}
The test fails on line2 with the inputs being null.
#Test
public void createPageParamsHttpException() throws HttpException, IOException, JAXBException {
expectedException.expect(AppException.class);
doNothing().when(decoder).marshal(Mockito.anyString(), Mockito.any(File.class));
doThrow(HttpException.class).when(client).executeMethod(Mockito.any(HttpMethod.class));
Params params = new Params(new Application(),
APPLICATION_URL_LABEL,
SITE_NAME_LABEL,
URL_WITHOUT_HTTP_N_HTML);
utility.createPage(params);
}
Any idea how should I proceed for the same?
You don't want to do this.
You are inherently changing the behavior of the class. If you change what two() does, how do you know that one() will do what it's supposed to do in production?
If you truly want to do this, you should extract the behavior of two() into another top level class, and then inject the dependency into A. Then you can mock this dependency and you don't have to worry about going to the trouble of creating a partial mock for A.
In a similar vein, if you must keep two in the same class (because it's behavior is part of the same responsibility that is assigned to A - see the Single Responsibility Principle - why is it public?
The reason you are having trouble is because you are violating the SRP, see my note above. You said this:
This builds a putRequest, executes it and returns a response.
You should not be trying to test the behavior of all three of those things at the same time. Ultimately, this method does not really do anything. The buildPUTRequest method does, and shouldn't be in a class called AUtility, it should be in a class RequestFactory. Then, you would want to test the Utils.buildResponse method, except that shouldn't be in a class called Utils, it should be in a class called Responder or something... and this method ABSOLUTELY should not be static.
Work on naming your classes better things, and if you can't come up with a good name, that means the class probably does too much and should be refactored. And a method that wraps the work in two other methods doesn't need to be unit tested. Integration tested, perhaps, but that's another story.
For public method calls, EasyMock's capture() allows you to intercept & examine arguments passed to the method. For private method calls, PowerMock's expectPrivate lets you mock private method calls.
Is there a way to somehow combine these and get the arguments passed to a private method call? Example:
public class Program
{
public FancyReturnType PublicMethod()
{
ArbitraryType localInstance = new ArbitraryType();
localInstance.setFoo(somePrivateHelperMethod());
localInstance.setBar(increasinglyComplexMagic());
long aLongValue = 11235L;
// more variables, more work
SomeType worker = privateHelperToIntercept(localInstance, aLongValue, otherVariables);
if (worker.something)
{
return retVal.aFancyReturnType;
}
else
{
return retVal.anotherFancyReturnType;
}
}
}
In this case, I want to examine the localInstance object as it is consumed by the privateHelperToIntercept() call.
I've found plenty of examples to mock private method calls; PowerMock's expectPrivate(partiallyMockedObject, "nameOfPrivateMethod", arg1, arg2) works great. I've also found examples to intercept arguments passed to public method calls; Capture<Type> myTestCapture = new Capture<Type>() combined with someMockedObject.PublicMethod(capture(myTestCapture)).
Unfortunately, I can neither get the two to work together, nor find examples of combining them. Has anyone seen a way to do this?
FWIW, I suspect Mockito can do this, but it's not included in our source/build/test system. I'd like to avoid the process of supporting new libraries in our system if possible.
If you are asking how to get a reference to localInstance, then the following code should suffice.
#PrepareForTest(Program.class)
public class Test {
#Test
public void testMethod() {
ArbitraryType passedLocalInstance = new ArbitraryType();
PowerMock.expectNew(ArbitraryType.class).andReturn(passedLocalInstance );
//remainder of the test method
assertEquals(14.2, passedLocalInstance .getValue());
}
}
Since java is pass-by-reference, the passedLocalInstance will be the argument passed into the method call. Did that answer your question?
new of any type is simply a static method. Deal with it in the same way... wrap it in a method, stub out the method. In this case you want to return a mock in your test, and then you can test all the interactions with that object (and remove dependency in your test on the code within the object you are creating which should have it's own tests)
public Program {
// your above code up to object creation
ArbitraryType localInstance = createArbitraryType();
// rest of your above code here
ArbitraryType createArbitraryType() {
return new ArbitraryType();
}
}
in your test...
public class MyTest {
TestableProgram extends Program {
#Override
ArbitraryType createArbitraryType() {
return this.arbitraryTypeMock;
}
}
private ArbitraryType arbitraryTypeMock;
private TestableMyClass objectToTest = new TestableProgram();
// rest of your tests...
}
Given your constraint's that's how I'd do it.
If could bend your constraints a bit I'd loosen up on the private methods, I've generally done away with private in favor of package default to make testing easier. If the folks IN your package are misbehaving, it's usually your code so private is mostly protecting you from yourself anyway. (but I know that isn't a valid answer your question as posed... ).