I would like to provide the same textual message for a group of assertions, something like
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
#Test
public void myTest() {
MyClass result = ...
withClue("the result {} does not conform", result.toString()) {
assertThat(result.id, notEmpty())
assertThat(result.xxxx, hasLength(33))
}
}
My expectation is that the "clue" will be shown before the first failed assertion. In Scala I'm used to ScalaTest withClue() that I usually use to show the full text representation of object (usually a JsonNode in my case) which usually allows me to understand better what went wrong.
So is there any way with vanilla JUnit, hamcrest of any other library dependency to get a message prepended to a group of assertions?
Related
public static ResponseBean call(Bean bean) throws Exception {
// statements...
IgnoreCall.ignoreMethodCall(bean);
// statements...
// return
}
With the code snippet above, is it possible to test the method ignoring invocation of IgnoreCall.ignoreMethod(Bean) without needing to place the entire statement under a boolean condition?
Here's the unit test code snippet:
#RunWith(PowerMockRunner.class)
#PrepareTest
public ClassHelperTest {
#Test
public void testCall() throws Excpetion {
// stubbing...
ResponseBean responseBean = ClassHelper.call(bean);
// verify/ies
// assert/s
}
}
Notes:
Refactoring ClassHelper.call(Bean) should be avoided. Even with a bad OO design, refactoring is costly.
Method signature is locked unless another pattern is applicable for replacement.
Tried using Mockito.when and PowerMockito.when on the target static method, stubbing didn't work on run-time debug.
As your comments indicate that changing your production code is not possible, you "simply" have to dive into the static-mocking aspects of PowerMock; as outlined here for example.
Basically you need to enable IgnoreCall for static mocking; and then you make calls to ignoreMethodCall() a no-op.
But as you keep asking: the core problem with your question is the fact that you want to mock out a static method that is void. I have a complete example below, but before that some explanations.
The point is: you call a method for two reasons:
It has a side effect
It returns a value, and maybe, causes a side effect, too
A void method can only be called for side effects. And the thing is: when you do static mocking, then that works on class level.
Meaning: you instruct PowerMock to "prevent" any of the static methods of some class from execution; you simply "erase" the side effects of all those static methods! So, by telling PowerMock to do those static mocks, all void methods are already "gone".
But as said, you might also call methods for their return value. And then is when the when() method of Mockito kicks in. You use that method to say: when that value-returning method is invoked, then do this or that.
Long story short; here is a [mcve] using the elements you asked for:
package ghostcat.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
class IgnoreCall {
public static void ignoreMethodCall(Object o) {
System.out.println("SHOULD NOT SHOW UP: " + o);
}
}
class CuT {
public static Object call(Object bean) {
System.out.println("statement1");
IgnoreCall.ignoreMethodCall(bean);
System.out.println("statement2");
return "whatever";
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(IgnoreCall.class)
public class PMTest {
#Test
public void test() {
PowerMockito.mockStatic(IgnoreCall.class);
CuT.call("yeha");
}
}
As in your example ... there is IgnoreCall; used within that a static method that I just called "call".
This prints:
statement1
statement2
When I go in and comment out
// PowerMockito.mockStatic(IgnoreCall.class);
It prints:
statement1
SHOULD NOT SHOW UP: yeha
statement2
So, a simple example that should tell you exactly what you need to do.
I worked with eclipse neon, IBM java8 JDK, and simply imported all the JARs from powermock-mockito-junit-1.6.6.zip into my test project.
I am testing out Grails static compilation, specifically GrailsCompileStatic. The documentation is limited in explaining what Grails dynamic features aren't supported. My test Controller is very simple, but I'm running into problems already.
#GrailsCompileStatic
class UserController {
UserService userService
def list() {
def model = [:]
def model = request.JSON
withFormat {
json {
render(model as JSON)
}
}
}
}
When compiling the application I get two compile time errors. The first about a missing property for JSON on the request object, and a second error about a missing method for json in the withFormat closure.
Seems to me I'm either doing something wrong or GrailsCompileStatic doesn't work with these features?
About request.JSON
The request object's getJSON() method is added via the ConvertersPluginSupport class. The exact lines are:
private static void enhanceRequest() {
// Methods for Reading JSON/XML from Requests
def getXMLMethod = { -> XML.parse((HttpServletRequest) delegate) }
def getJSONMethod = { -> JSON.parse((HttpServletRequest) delegate)}
def requestMc = GrailsMetaClassUtils.getExpandoMetaClass(HttpServletRequest)
requestMc.getXML = getXMLMethod
requestMc.getJSON = getJSONMethod
}
As you can see it uses the dynamic dispatch mechanism, but fortunately it's not such a big deal. You can simply replicate it by executing JSON.parse(request) anywhere in your controller.
Pay attention though! JSON.parse(HttpServletRequest) returns an Object, which is either a JSONObject or a JSONArray, so if you plan on using them explicitly, and you are compiling statically, you will have to cast it.
You might create a common base class for your controllers:
import org.codehaus.groovy.grails.web.json.JSONArray
import org.codehaus.groovy.grails.web.json.JSONObject
import grails.converters.JSON
#GrailsCompileStatic
class BaseController {
protected JSONObject getJSONObject() {
(JSONObject) JSON.parse(request)
}
protected JSONArray getJSONArray() {
(JSONArray) JSON.parse(request)
}
}
Then in your controller you can simpy invoke getJSONObject() or getJSONArray. It's a bit of a workaround, but results in a staticly compileable code.
About withFormat
This is a bit more complicated. The withFormat construct is really a method, which has a Closure as it's first parameter. The internal implementation then figures out based on the current request or response content type which part of the argument closure is to be used.
If you want to figure out how to do this statically, take a look at the source code.
You could extend this class, then use it's protected methods, but I don't know if it's worth all the hussle, you would loose much of Grails' conciseness. But if you really want to do it, you can. Don't you just love open source projects ? :)
I have a problem with Spock Mock() object.
I have a java class I'm trying to test. This class does some ftp stuff I want to mock.
My sample code
class ReceiveDataTest extends Specification{
String downloadPath = 'downloadPath';
String downloadRegex = 'downloadRegex';
SftpUtils sftpUtils = Mock();
ReceiveData receiveData;
def setup(){
sftpUtils.getFileNames(downloadPath,downloadRegex) >> ['file1', 'file2']
receiveData= new ReceiveData()
receiveData.setDownloadPath(downloadPath)
receiveData.setDownloadRegex(downloadRegex)
receiveData.setSftpUtils(sftpUtils);
}
def "test execute"() {
given:
def files = sftpUtils.getFileNames(downloadPath,downloadRegex)
files.each{println it}
when:
receiveData.execute();
then:
1*sftpUtils.getFileNames(downloadPath,downloadRegex)
}
}
public class ReceiveData(){
//fields, setters etc
public void execute() {
List<String> fileNames = sftpUtils.getFileNames(downloadPath, downloadRegex);
for (String name : fileNames) {
//dowload and process logic
}
}
}
Now, inside "test execute" the files.each{} prints what is expected. But when receiveData.execute() is called my sftpUtils are returning null..
Any ideas why?
EDIT
Maybe i didnt state my problem well - that I dont want to just check if getFileNames was called. I need the result to proper check the for loop. If I comment the loop inside execute, the test passes. But since I use the result of the getFilenames() method, I get a NPE execute method reaches the for loop. With mockito I would do something like this
Mockito.when(sftpUtils.getFilenames(downloadPath, downloadRegex)).thenReturn(filenamesList);
receiveData.execute();
Mockito.verify(sftpUtils).getFilenames(downloadPath, downloadRegex);
//this is what I want to test and resides inside for loop
Mockito.verify(sftpUtils).download(downloadPath, filenamesList.get(0));
Mockito.verify(sftpUtils).delete(downloadPath, filenamesList.get(0));
but I cannot use Mockito.verify() inside Spock then block
The main problem is that you did not include the response generator (the >> part) in the expectation (i.e. the "1 * ..." part inside the then: block).
This is explained well in the spock documentation.
http://spockframework.org/spock/docs/1.0/interaction_based_testing.html#_combining_mocking_and_stubbing
https://spock-framework.readthedocs.org/en/latest/interaction_based_testing.html#wheretodeclareinteractions
You shouldn't have to declare your stub in the setup: block. You can just specifiy it once in the then: block -- even though that follows the call to receiveData.execute(). That's part of the magic of spock thanks to Groovy AST transformations. And since (non-shared) fields are reinitialized before each test (more AST based magic), you don't even need setup() in this case.
Another odd thing is that you are both stubbing out sftpUtils.getFilenames() and also calling it from the test code. Mocks and stubs are intended to replace collaborators that are called from the system under test. There's no reason to call the stub from the test driver. So delete the call to getFilenames() from your given block and let the code under test call it instead (as it does).
Groovy lets you simplify calls to Java set and get methods. Look at the initialization of receiveData below. Its okay to use def in Groovy. Let the compiler figure out the data types for you.
Leading to something like:
class ReceiveDataTest extends Specification {
// only use static for constants with spock
static String PATH = 'downloadPath'
static String REGEX = 'downloadRegex'
def mockSftpUtils = Mock(SftpUtils)
def receiveData = new ReceiveData(downloadPath : PATH,
downloadRegex : REGEX,
sftpUtils : mockSftpUtils)
def "execute() calls getFileNames() exactly once"() {
when:
receiveData.execute()
then:
1 * mockSftpUtils.getFileNames(PATH, REGEX) >> ['file1', 'file2']
0 * mockSftpUtils.getFileNames(_,_)
// The second line asserts that getFileNames() is never called
// with any arguments other than PATH and REGEX, aka strict mocking
// Order matters! If you swap the lines, the more specific rule would never match
}
}
I'd like to be able to use JUnit 4.7's ExpectedException #Rule in Scala. However, it doesn't seem to catch anything:
import org.junit._
class ExceptionsHappen {
#Rule
def thrown = rules.ExpectedException.none
#Test
def badInt: Unit = {
thrown.expect(classOf[NumberFormatException])
Integer.parseInt("one")
}
}
This still fails with a NumberFormatException.
To make this work with JUnit 4.11 in Scala, you should meta-annotate your annotation so that the annotation is applied only to the (synthetic) getter method, not the underlying field:
import org.junit._
import scala.annotation.meta.getter
class ExceptionsHappen {
#(Rule #getter)
var thrown = rules.ExpectedException.none
#Test
def badInt: Unit = {
thrown.expect(classOf[NumberFormatException])
Integer.parseInt("one")
}
}
EDIT: Following the release of JUnit 4.11, you can now annotate a method with #Rule.
You will use it like:
private TemporaryFolder folder = new TemporaryFolder();
#Rule
public TemporaryFolder getFolder() {
return folder;
}
For earlier versions of JUnit, see the answer below.
--
No, you can't use this directly from Scala. The field needs to be public and non-static. From
org.junit.Rule:
public #interface Rule: Annotates fields that contain rules. Such a field must be public, not static, and a subtype of TestRule.
You cannot declare a public fields in Scala. All fields are private, and made accessible by accessors. See the answer to this question.
As well as this, there is already an enhancement request for junit (still Open):
Extend rules to support #Rule public MethodRule someRule() { return new SomeRule(); }
The other option is that it non-public fields be allowed, but this has already been rejected: Allow #Rule annotation on non-public fields.
So your options are:
clone junit, and implement the first suggestion, the method, and submit a pull request
Extend the Scala class from a java class which implements the #Rule
-
public class ExpectedExceptionTest {
#Rule
public ExpectedException thrown = ExpectedException.none();
}
and then inheriting from that:
class ExceptionsHappen extends ExpectedExceptionTest {
#Test
def badInt: Unit = {
thrown.expect(classOf[NumberFormatException])
Integer.parseInt("one")
}
}
which works correctly.
As a very newbie to Scala I am just using a very simple workaround: explicitly catch the exception and fail if your expected exception is not thrown.
Below is a sample skeleton:
try {
*your code that should throw an exception*
fail("Did not generate *the.Exception.you.expect*")
} catch {
case t: *the.Exception.you.expect* => // do nothing, it's expected :)
}
Without knowing JUnit rules, and without testing it, because I don't have an appropriate setup at hand, I go out on a limb and suggest turning thrown into a val.
I guess its some member that is initialized with something and then it gets some state and then some other machinery checks the state against something. You are always creating new ones and keep forgetting the expectation.
If Scala has something similar like static imports, then catch-exception is an alternative to JUnit 4.7's ExpectedException #Rule.
I'm still using JUnit 4, and found #Juh_'s comment instructive. This worked in Scala 2.11.0.
import org.junit.rules.ExpectedException
import org.junit.{Rule, Test}
import scala.reflect.{ClassTag, classTag}
class DeleteMe {
object Thrower {
def throwException[R <: Throwable: ClassTag](message: String): Unit = {
throw classTag[R].runtimeClass.getConstructor(classOf[String]).newInstance(message).asInstanceOf[R]
}
}
#Rule
def exceptionRule:ExpectedException = ExpectedException.none()
#Test(expected = classOf[Exception])
def checkConversionExceptions = {
val myMessage = "My Message"
exceptionRule.expectMessage(myMessage)
Thrower.throwException[Exception](myMessage)
()
}
}
I have successfully set up a quick test of creating a "REST-like" service that returns an object serialized to JSON, and that was quite easy and quick (based on this article).
But while returning JSON-ified objects was easy as peach, I have yet to see any examples dealing with input parameters that are not primitives. How can I pass in a complex object as an argument? I am using Apache CXF, but examples using other frameworks like Jackson are welcome too :)
Client side would probably be something like building a javascript object, pass it into JSON.stringify(complexObj), and pass that string as one of the parameters.
The service would probably look something like this
#Service("myService")
class RestService {
#GET
#Produces("application/json")
#Path("/fooBar")
public Result fooBar(#QueryParam("foo") double foo, #QueryParam("bar") double bar,
#QueryParam("object") MyComplex object) throws WebServiceException {
...
}
}
Sending serialized objects as parameters would probably quickly touch the 2KB URL-limit imposed by Internet Explorer. Would you recommend using POST in these cases, and would I need to change much in the function definitions?
After digging a bit I quickly found out there are basically two options:
Option 1
You pass a "wrapper object" containing all the other parameters to the service. You might need to annotate this wrapper class with JAXB annotations like #XmlRootElement in order for this to work with the Jettison based provider, but if you use Jackson in stead there is no need. Just set the content type to the right type and the right message body reader will be invoked.
This will only work for POST type services of course (AFAIK).
Example
This is just an example of turning the service mentioned in the original question into one using a wrapper object.
#Service("myService")
class RestService {
#POST
#Produces("application/json")
#Path("/fooBar")
public Result fooBar(
/**
* Using "" will inject all form params directly into a ParamsWrapper
* #see http://cxf.apache.org/docs/jax-rs-basics.html
*/
#FormParam("") FooBarParamsWrapper wrapper
) throws WebServiceException {
doSomething(wrapper.foo);
}
}
class ParamsWrapper {
double foo, bar;
MyComplexObject object;
}
Option 2
You can provide some special string format that you pack your objects into and then implement either a constructor taking a string, a static valueOf(String s) or a static fromString(String s) in the class that will take this string and create an object from it. Or quite similar, create a ParameterHandler that does exactly the same.
AFAIK, only the second version will allow you to call your services from a browser using JSONP (since JSONP is a trick restricted to GET). I chose this route to be able to pass arrays of complex objects in the URI.
As an example of how this works, take the following domain class and service
Example
#GET
#Path("myService")
public void myService(#QueryParam("a") MyClass [] myVals) {
//do something
}
class MyClass {
public int foo;
public int bar;
/** Deserializes an Object of class MyClass from its JSON representation */
public static MyClass fromString(String jsonRepresentation) {
ObjectMapper mapper = new ObjectMapper(); //Jackson's JSON marshaller
MyClass o= null;
try {
o = mapper.readValue(jsonRepresentation, MyClass.class );
} catch (IOException e) {
throw new WebApplicationException()
}
return o;
}
}
A URI http://my-server.com/myService?a={"foo":1, "bar":2}&a={"foo":100, "bar":200} would in this case be deserialized into an array composed of two MyClass objects.
2019 comment:
Seeing that this answer still gets some hits in 2019, I feel I should comment. In hindsight, I would not recomment option 2, as going through these steps just to be able to be able to do GET calls adds complexity that's probably not worth it. If your service takes such complex input, you will probably not be able to utilize client side caching anyway, due to the number of permutations of your input. I'd just go for configuring proper Cross-Origin-Sharing (CORS) headers on the server and POST the input. Then focus on caching whatever you can on the server.
The accepted answer is missing #BeanParam. See
https://docs.jboss.org/resteasy/docs/3.0-rc-1/javadocs/javax/ws/rs/BeanParam.html
for further details. It allows you to define query params inside a wrapper object.
E.g.
public class TestPOJO {
#QueryParam("someQueryParam")
private boolean someQueryParam;
public boolean isSomeQueryParam() {
return someQueryParam;
}
public boolean setSomeQueryParam(boolean value) {
this.someQueryParam = value;
}
}
... // inside the Resource class
#GET
#Path("test")
public Response getTest(#BeanParam TestPOJO testPOJO) {
...
}
the best and simplest solution is to send your object as a json string and in server side implement a method which will decode that json and map to the specified object as per your need.. and yes it`s better to use POST.