I have a test that doesn't fail when it should:
import static org.assertj.core.api.Assertions.assertThat;
#Test
public void testTransactionResponse() {
String id= "004";
long amount= 5000001L;
TransactionResource transactionResource = buildTransactionResource(amount, "EUR");
System.out.println(transactionController.create(id, transactionResource).getStatusCode()); //the output is 403
assertThat(transactionController.create(id, transactionResource).getStatusCode().equals(200)); //is true and test doesn't fail
}
How is it possible?
assertThat returns BooleanAssert and doesn't actually assert anything.
AssertJ provides fluent API so you're expected to call assert methods after that:
assertThat(
transactionController.create(id, transactionResource).getStatusCode().equals(200)
).isTrue();
But it doesn't seem that you need AssertJ for that. JUnit's own assertTrue would suffice:
assertTrue(transactionController.create(id, transactionResource).getStatusCode().equals(200));
or even better, assertEquals:
assertEquals(200, transactionController.create(id, transactionResource).getStatusCode());
I would use:
assertThat(operation.getStatusCode()).isEqualTo(200);
As #default locale stated, it is true that assertThat(false) does not check anything, you can detect this bad usage with findbugs as explained here http://joel-costigliola.github.io/assertj/assertj-core.html#faq-incorrect-api-usage.
Related
I have my ServiveImpl class, which has public methods to create and delete index from AEM to Solr. How can we handle the Junit for these void methods using Mockito? Any pointers will be help. Mainly for testing integration with Solr
In this case, your JUnit wouldn't really make any difference other than giving you some test coverage.
The reason behind writing a Junit is to ensure that a method returns a result, or throws an exception. With a void method, the only thing that can be tested is that the method executes.
To solve this, it would be good to at least return a boolean value. Without this, you can never be sure whether the index was really deleted or not.
So the suggestion here would be-
Update the method to ensure the correct error handling takes place.
Based on the method execution, return a boolean value at least. This will not have any impact on your project because the method was void anyway and no calls would be impacted.
In your Junit, assert the returned value as true or false, or just use the assertTrue method.
boolean deleteIndex(String indexName) {
if (deleted) {
return true;
} else {
return false;
}
}
JUnit-
#InjectMocks
private ServiveImpl service = new ServiveImpl();
#Test
public void testIndexDeletion() {
boolean indexDeleted = ServiveImpl.deleteIndex("someIndex");
assertTrue(indexDeleted);
}
I'm using Mockito 1.9.0. I want mock the behaviour for a single method of a class in a JUnit test, so I have
final MyClass myClassSpy = Mockito.spy(myInstance);
Mockito.when(myClassSpy.method1()).thenReturn(myResults);
The problem is, in the second line, myClassSpy.method1() is actually getting called, resulting in an exception. The only reason I'm using mocks is so that later, whenever myClassSpy.method1() is called, the real method won't be called and the myResults object will be returned.
MyClass is an interface and myInstance is an implementation of that, if that matters.
What do I need to do to correct this spying behaviour?
Let me quote the official documentation:
Important gotcha on spying real objects!
Sometimes it's impossible to use when(Object) for stubbing spies. Example:
List list = new LinkedList();
List spy = spy(list);
// Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
// You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
In your case it goes something like:
doReturn(resultsIWant).when(myClassSpy).method1();
In my case, using Mockito 2.0, I had to change all the any() parameters to nullable() in order to stub the real call.
My case was different from the accepted answer. I was trying to mock a package-private method for an instance that did not live in that package
package common;
public class AnimalĀ {
void packageProtected();
}
package instances;
class Dog extends Animal { }
and the test classes
package common;
public abstract class AnimalTest<T extends Animal> {
#Before
setup(){
doNothing().when(getInstance()).packageProtected();
}
abstract T getInstance();
}
package instances;
class DogTest extends AnimalTest<Dog> {
Dog getInstance(){
return spy(new Dog());
}
#Test
public void myTest(){}
}
The compilation is correct, but when it tries to setup the test, it invokes the real method instead.
Declaring the method protected or public fixes the issue, tho it's not a clean solution.
The answer by Tomasz Nurkiewicz appears not to tell the whole story!
NB Mockito version: 1.10.19.
I am very much a Mockito newb, so can't explain the following behaviour: if there's an expert out there who can improve this answer, please feel free.
The method in question here, getContentStringValue, is NOT final and NOT static.
This line does call the original method getContentStringValue:
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));
This line does not call the original method getContentStringValue:
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));
For reasons which I can't answer, using isA() causes the intended (?) "do not call method" behaviour of doReturn to fail.
Let's look at the method signatures involved here: they are both static methods of Matchers. Both are said by the Javadoc to return null, which is a little difficult to get your head around in itself. Presumably the Class object passed as the parameter is examined but the result either never calculated or discarded. Given that null can stand for any class and that you are hoping for the mocked method not to be called, couldn't the signatures of isA( ... ) and any( ... ) just return null rather than a generic parameter* <T>?
Anyway:
public static <T> T isA(java.lang.Class<T> clazz)
public static <T> T any(java.lang.Class<T> clazz)
The API documentation does not give any clue about this. It also seems to say the need for such "do not call method" behaviour is "very rare". Personally I use this technique all the time: typically I find that mocking involves a few lines which "set the scene" ... followed by calling a method which then "plays out" the scene in the mock context which you have staged... and while you are setting up the scenery and the props the last thing you want is for the actors to enter stage left and start acting their hearts out...
But this is way beyond my pay grade... I invite explanations from any passing Mockito high priests...
* is "generic parameter" the right term?
One more possible scenario which may causing issues with spies is when you're testing spring beans (with spring test framework) or some other framework that is proxing your objects during test.
Example
#Autowired
private MonitoringDocumentsRepository repository
void test(){
repository = Mockito.spy(repository)
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
In above code both Spring and Mockito will try to proxy your MonitoringDocumentsRepository object, but Spring will be first, which will cause real call of findMonitoringDocuments method. If we debug our code just after putting a spy on repository object it will look like this inside debugger:
repository = MonitoringDocumentsRepository$$EnhancerBySpringCGLIB$$MockitoMock$
#SpyBean to the rescue
If instead #Autowired annotation we use #SpyBean annotation, we will solve above problem, the SpyBean annotation will also inject repository object but it will be firstly proxied by Mockito and will look like this inside debugger
repository = MonitoringDocumentsRepository$$MockitoMock$$EnhancerBySpringCGLIB$
and here is the code:
#SpyBean
private MonitoringDocumentsRepository repository
void test(){
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
Important gotcha on spying real objects
When stubbing a method using spies , please use doReturn() family of methods.
when(Object) would result in calling the actual method that can throw exceptions.
List spy = spy(new LinkedList());
//Incorrect , spy.get() will throw IndexOutOfBoundsException
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
I've found yet another reason for spy to call the original method.
Someone had the idea to mock a final class, and found about MockMaker:
As this works differently to our current mechanism and this one has different limitations and as we want to gather experience and user feedback, this feature had to be explicitly activated to be available ; it can be done via the mockito extension mechanism by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line: mock-maker-inline
Source: https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#mock-the-unmockable-opt-in-mocking-of-final-classesmethods
After I merged and brought that file to my machine, my tests failed.
I just had to remove the line (or the file), and spy() worked.
One way to make sure a method from a class is not called is to override the method with a dummy.
WebFormCreatorActivity activity = spy(new WebFormCreatorActivity(clientFactory) {//spy(new WebFormCreatorActivity(clientFactory));
#Override
public void select(TreeItem i) {
log.debug("SELECT");
};
});
As mentioned in some of the comments, my method was "static" (though being called on by an instance of the class)
public class A {
static void myMethod() {...}
}
A instance = spy(new A());
verify(instance).myMethod(); // still calls the original method because it's static
Work around was make an instance method or upgrade Mockito to a newer version with some config: https://stackoverflow.com/a/62860455/32453
Bit late to the party but above solutions did not work for me , so sharing my 0.02$
Mokcito version: 1.10.19
MyClass.java
private int handleAction(List<String> argList, String action)
Test.java
MyClass spy = PowerMockito.spy(new MyClass());
Following did NOT work for me (actual method was being called):
1.
doReturn(0).when(spy , "handleAction", ListUtils.EMPTY_LIST, new String());
2.
doReturn(0).when(spy , "handleAction", any(), anyString());
3.
doReturn(0).when(spy , "handleAction", null, null);
Following WORKED:
doReturn(0).when(spy , "handleAction", any(List.class), anyString());
I have some code which works Ok with jodd 3.9.1 and I want to upgrade it to jodd version 4.1.4. but I have some errors:
Example:
#POST #Action
public String save(){
... some code for validation
if (!valid){
return VTOR_JSON; //Error
}
service.store(Object);
return NONE; //Error
}
Exception:
jodd.madvoc.MadvocException: Invalid result name:vtor_json (or Invalid result name:none)
at jodd.madvoc.component.ResultsManager.lookup(ResultsManager.java:181)
at jodd.madvoc.component.MadvocController.render(MadvocController.java:183)
at jodd.madvoc.ActionRequest.lambda$createExecutionArray$0(ActionRequest.java:208)
at jodd.madvoc.ActionRequest.invoke(ActionRequest.java:237)
at jodd.madvoc.component.MadvocController.invoke(MadvocController.java:154)
at jodd.madvoc.MadvocServletFilter.doFilter(MadvocServletFilter.java:108)
What is the problem?
How to solve this?
igr, Thanks for your answer.
I try your sugestion and that's works.
But, I have some additional code:
Example:
public Object save(){
if (!authorized()){
return Redirect.to(AuthAction.ALIAS_ACCESS_DENIED); //don't work
}
if (!valid){
return JsonResult.of(vtor.getViolations()); //work
}
....
return null; //work
}
Here is debug output
38675 [DEBUG] j.m.r.AbstractTemplateViewActionResult.render:79 - new target: /accessDenied:
38676 [DEBUG] j.m.r.ServletDispatcherActionResult.targetExists:99 - target check: /accessDenied.jspf
38676 [DEBUG] j.m.r.ServletDispatcherActionResult.targetExists:99 - target check: /accessDenied.jsp
38676 [DEBUG] j.m.r.AbstractTemplateViewActionResult.render:90 - target found: /accessDenied.jsp
But , never redirect to accessDenied.html.
I try with Object but it doesn't work.
Any suggest?
I found the solution:
if (!valid){
return JsonResult.of(VtorUtil.createViolationsJsonString(request, vtor.getViolations())).value();
}
It's very easy like you said, igr ;-)
Let me explain:)
With Jodd v4 we don't have anymore the VTOR_JSON type of results - those that return strings. (The string constant is still there, but it is not used). We had to remove this way of returning results as it is not scalable - simply can not add easily different result types.
How to fix it?
We are back to basic :) VTOR_JSON was returning the JSON with the error. So now you have few options (as you can see here):
return an object annotated with #RenderWith annotation;
put a #RenderWith annotation on the action;
return a PathResult helper object;
specify the result in the action configuration.
In a short, you should do this by yourself - but don't worry its super easy. For example, you can return:
if (!valid) {
return JsonResult.of(violations());
}
return null;
If null is not working, try returning new NoneActionResult() (sorry, we will add more convenient way).
Checkout the results package: results.
Sorry for this transition, it is really for good purpose. We will add more helpers like JsonResult. And of course, if you need any support, let us know.
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
}
}
If writing a Java unit test with mocking using JMock, should we use
Mockery context = new Mockery()
or
Mockery context = new JUnit4Mockery()
What is the difference between the two, and when should we use which?
#Rhys It's not the JUnit4Mockery that replaces the need to call assertIsSatisfied, its the JMock.class (combined with the #RunWith). You wont need to call assertIsSatisfied when you create a regular Mockery.
The JUnit4Mockery translates errors.
By default, expectation exceptions are reported in Junit as ExpectationError, so for example, using
Mockery context = new Mockery();
you'll get
unexpected invocation: bar.bar()
no expectations specified: did you...
- forget to start an expectation with a cardinality clause?
- call a mocked method to specify the parameter of an expectation?
and using,
Mockery context = new JUnit4Mockery();
you'll get
java.lang.AssertionError: unexpected invocation: bar.bar()
no expectations specified: did you...
- forget to start an expectation with a cardinality clause?
- call a mocked method to specify the parameter of an expectation?
what happened before this: nothing!
The JUnit4Mockery converted the ExpectationError to an java.lang.AssertionError which JUnit deals with. Net result is that it'll show up in your JUnit report as an failure (using JUnit4Mockery) rather than an error.
When using JMock with JUnit 4, you can avoid some boilerplate code by taking advantage of the JMock test runner. When you do this, you must use the JUnit4Mockery instead of the regular Mockery.
Here is how you'd structure a JUnit 4 test:
#RunWith(JMock.class)
public void SomeTest() {
Mockery context = new JUnit4Mockery();
}
The main advantage is there is no need to call assertIsSatisfied in each test, it is called automatically after each test.
Better yet, per http://incubator.apache.org/isis/core/testsupport/apidocs/org/jmock/integration/junit4/JUnitRuleMockery.html use #Rule and avoid #RunWith which you might need for some other system:
public class ATestWithSatisfiedExpectations {
#Rule
public final JUnitRuleMockery context = new JUnitRuleMockery();
private final Runnable runnable = context.mock(Runnable.class);
#Test
public void doesSatisfyExpectations() {
context.checking(new Expectations() {
{
oneOf(runnable).run();
}
});
runnable.run();
}
}