As a beginner for Mockito Junit, this may sound very dump question, but I'd still like to confirm:
Class1 input1;
#Mock
Class2 input2;
private Class3 obj;
#Before
public void setup() {
this obj = new Class3(input1, input2);
}
#Test
public void doTest() {
val result1 = obj.method1(input1); // return sth.
val result2 = obj.method2(input2); // return null.
}
So input1 and input2 are passed into Class3 obj, but only input2 is Mocked dependency. Then I found when I call method2 which relies on input2, it simply returns null.
So whatever mocked class is essentially null? That's why we need to use when...thenReturn for mocked class? After all, our purpose is to test major function, but not dependency.
Is my understanding correct?
A mocked class is not null. It is a skeleton with the same signature as the original class, but without the implementation. It is instrumented to 'see' the calls to all methods, so it can be verified afterwards. A mock is therefor an object that does not work. It can't store data and it can't execute methods. You can only control all calls to it and all return values of the mock. If you need some more advanced mocks you should use a #Spy. A spy is a 'mock' but with the original implementation: it is an instrumented class to detect all calls to it and control output, BUT also has the original storage facilities and real calls.
Another way to do real calls is by this construction:
Mockito.when(myMockedObject).thenCallRealMethod();
In unit testing it is best practice to ONLY test the one class you are testing, without the underlying classes. It sounds like an open door, but it really is not. All the classes that are used by the class you are testing should be mocked. With the mock you have full control on return values and you can test all corner-cases for that class. All classes that are mocked should be tested themselves by their own unit tests. This brings the next issue: all classes that are used should be injectable or changeable by the test. Instead of a real DB driver you want to be able to inject a mock so you can see if all the right calls are made.
Yes your understanding is correct.
If you have used the appropriate runner (junit4) or extension (junit5), your mocked object is not null (even if its toString method may return something looking like "null").
However, what may be a problem is that your Class3#method2 uses a method of the mock of Class2 that is returning null.
In fact, that behavior is wanted. Here you have the choice between :
make your mock return deep stubs using the annotation #Mock (answer = Answers.RETURNS_DEEP_STUBS), this way any method of Class2 (that is not final nor returning a primitive or wrapper type) will return a mock, and any method of this mock will return a mock and so on.
declare explicitly how the mock should behave with something like: Mockito.when(input2.myMethod()).thenReturn("test");. The subbing API supplied by Mockito is well documented: https://static.javadoc.io/org.mockito/mockito-core/2.23.0/org/mockito/Mockito.html#stubbing
Hope this helps,
Related
I have a method which needs to be called instead of the real method.
Instead I get an exception. Can somebody please help me with right way to call the alternate method through mockito ?
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 4 recorded.
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
//Code starts here
class A{
public realMethod(String s, Foo f){
}
}
class B {
public mockMethod(String s, Foo f) {
}
}
class UnitTestClass{
ClassA mock = new ClassA();
mock.when(realMethod(any(String.class), any(Foo.class))).thenReturn(mockMethod(any(String.class),any(Foo.class));
}
You are getting mocking wrong.
Here:
thenReturn(mockMethod(any(String.class),any(Foo.class));
That simply doesn't make sense.
Mocking works like this:
you create a mock object of some class, like A mock = mock(A.class)
you specify interactions on that mock object
Your code implies that you think that these specifications are working like "normal" code - but they do not!
What you want to do: when some object is called with certain parameters, then return the result of another method call.
Like in:
when(a.foo(x, y)).thenReturn(b.bar(x, y))
That is what want you intend to do. But thing is: it isn't that easy. You can't use the any() matcher in thee thenReturn part in order to "provide" the arguments that were passed in the when() call before! It is that simply.
Mocking should be within a specific unit test to get a specific result.
Meaning: you are not writing an ordinary program where it would make any sense to "forward" parameters to another call. In other words; your code should more look like:
when(mock.realMethod("a", someSpecificFoo)).thenReturn(mockMethod("a", someSpecificFoo))
That is the only thing possible here.
Beyond that, you might want to look into a Mockito enter link description here instead.
Long story short: it simply looks like you don't understand how to use mocking frameworks. I suggest that you step back and read/work various tutorials. This is not something you learn by trial and error.
How to mock a void protected Method in a filter using mockito and make it return some "response"
since it's a void method ,i cannot use doReturn(some value) ,is there a way to set a response and make
it return that.
The short answer is that you can't, the long answer is that even if you could, you shouldn't.
The purpose of your test should be to verify the behaviour of your class/method. What does your filter do? What are the possible paths through the code? It must either return a value, have a side-effect or communicate with another object. These are the things that you should be testing for.
For example, seeing as this is a filter chain I assume that it's going to apply some logic and either call the next filter or not. You should mock the next filter in the chain and assert that it's called correctly or not depending on your logic.
I don't think we can return any response from methods that returns void but in case if we want to mock a method that returns void we could use:
Mockito.doNothing().when(apiService).methodNamethatReturnsVoid(Mockito.anyString();
I am testing a Restful endpoint in my JUnit and getting an exception as below in the
list which is present as an argument inside the save method,
**"Argument(s) are different! Wanted:"**
save(
"121",
[com.domain.PP#6809cf9d,
com.domain.PP#5925d603]
);
Actual invocation has different arguments:
save(
"121",
[com.domain.PP#5b6e23fd,
com.domain.PP#1791fe40]
);
When I debugged the code, the code broke at the verify line below and threw the
above exception. Looks like the arguments inside the "testpPList" within the save
method is different. I dont know how it becomes different as I construct them in my
JUNit properly and then RestFul URL is invoked.
Requesting your valuable inputs. Thanks.
Code:
#Test
public void testSelected() throws Exception {
mockMvc.perform(put("/endpointURL")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(testObject)))
.andExpect(status().isOk());
verify(programServiceMock, times(1)).save(id, testpPList);
verifyNoMoreInteractions(programServiceMock);
}
Controller method:
#RequestMapping(value = "/endpointURL", method = RequestMethod.PUT)
public #ResponseBody void uPP(#PathVariable String id, #RequestBody List<PPView> pPViews) {
// Code to construct the list which is passed into the save method below
save(id, pPList);
}
Implementing the Object#equals(Object) can solve it by the equality comparison. Nonetheless, sometimes the object you are validating cannot be changed or its equals function can not be implemented. For such cases, it's recommended using org.mockito.Matchers#refEq(T value, String... excludeFields). So you may use something like:
verify(programServiceMock, times(1)).save(id, refEq(testpPList));
Just wrapping the argument with refEq solves the problem.
Make sure you implement the equals method in com.domain.PP.
[Edit]
The reasoning for this conclusion is that your failed test message states that it expects this list of PP
[com.domain.PP#6809cf9d, com.domain.PP#5925d603]
but it's getting this list of PP
[com.domain.PP#5b6e23fd, com.domain.PP#1791fe40]
The hex values after the # symbol for each PP object is their hash codes. Because they are different, then it shows that they belong to different objects. So the default implementation of equals will say they're not equal, which is what verify() uses.
It's good practice to also implement hashCode() whenever you implement equals(): According to the definition of hashCode, two objects that are equal MUST have equal hashCodes. This ensures that objects like HashMap can use hashCode inequality as a shortcut for object inequality (here, placing objects with different hashCodes in different buckets).
I am using jUnit to manage integration tests for an application that accesses a database. Because setting up the test data is a time-consuming operation, I have been doing that in the #BeforeClass method, which is executed only once per test class (as opposed to the #Before method, which is run once per test method).
Now I want to try a few different permutations for the configuration of the data layer, running all of my tests on each different configuration. This seems like a natural use of the Parameterized test runner. Problem is, Parameterized supplies parameters to the class constructor, and the #BeforeClass method is abstract and is called before the class constructor.
A few questions,
Does Parameterized call the #BeforeClass method for each permutation of parameters, or does it only call once?
If the #BeforeClass method is called repeatedly, is there some way to access the parameter values from inside of it?
If none of these, what do people suggest as the best alternative approach to this problem?
I think you are going to need a custom test runner. I'm having the same issue you are having (needing to run the same tests using multiple, expensive configurations). You'd need a way to parameterize the set up, perhaps using #Parameter annotations similar to those used by the Parameterized runner but on static member fields instead of instance fields. The custom runner would have to find all static member fields with the #Parameter annotation and then run the test class (probably using the basic BlockJunit4ClassRunner) once per static #Parameter field. The #Parameter field should probably be a #ClassRule.
Andy on Software has done a good job of developing custom test runners, and he explains so pretty clearly in these blog posts here and here.
#BeforeClass is only called once in your example. Which makes sense given the name - before class!
If your tests require different data, there are two choices I can think of:
Set up that data in #Before so it is test specific
Group the tests that you want to run with the same data into separate test classes and use #BeforeClass for each one.
You can call this initialization logic in the constructor of your test class. Keep track of the last parameter used in a static variable. When it changes, set up the class for the new parameter.
I can't think of an equivalent for AfterClass.
This is an old question, but I just had to solve a probably similar problem. I went with the solution below for now, which essentially is an implementation of TREE's (updated) answer with using a generic abstract base class in order to avoid duplication whenever you need this mechanism.
Concrete tests would provide a #Parameters method that return an iterable of single-element arrays containing a Supplier< T > each. Those suppliers are then executed exactly once per actual input needed by the concrete test methods.
#RunWith(Parameterized.class)
public class AbstractBufferedInputTest<T> {
private static Object INPUT_BUFFER;
private static Object PROVIDER_OF_BUFFERED_INPUT;
private T currentInput;
#SuppressWarnings("unchecked")
public AbstractBufferedInputTest(Supplier<T> inputSuppler) {
if (PROVIDER_OF_BUFFERED_INPUT != inputSuppler) {
INPUT_BUFFER = inputSuppler.get();
PROVIDER_OF_BUFFERED_INPUT = inputSuppler;
}
currentInput = (T) INPUT_BUFFER;
}
/**
*
* #return the input to be used by test methods
*/
public T getCurrentInput() {
return currentInput;
}
}
You could do your initialization in a #Before method, writing to an instance variable but testing for null.
#RunWith(value = Parameterized.class)
public class BigThingTests {
private BigThing bigThing;
#Before
public void createBitThing() {
if (bigThing == null) {
bigThing = new BigThing();
}
}
...
}
A new instance of BigThingTests is created for each set of parameters, and bigThing is set to null with each new instance. The Parameterized runner is single-threaded, so you don't have to worry about multiple initializations.
Let say I have a test class called MyTest.
In it I have three tests.
public class MyTest {
AnObject object;
#Before
public void setup(){
object = new AnObject();
object.setSomeValue(aValue);
}
#Test
public void testMyFirstMethod(){
object.setAnotherValue(anotherValue);
// do some assertion to test that the functionality works
assertSomething(sometest);
}
#Test
public void testMySecondMethod(){
AValue val = object.getAnotherValue();
object.doSomethingElse(val);
// do some assertion to test that the functionality works
assertSomething(sometest);
}
Is there any way I can use the value of anotherValue, which is set with its setter in the first test, in the second test. I am using this for testing database functionality. When I create an object in the DB I want to get its GUID so I can use this to do updates and deletes in later test methods, without having to hardcode the GUID and therefore making it irrelevant for future use.
You are introducing a dependency between two tests. JUnit deliberately does not support dependency between tests, and you can't guarantee the order of execution (except for test classes in a test suite, see my answer to Has JUnit4 begun supporting ordering of test? Is it intentional?). So you really want to have dependencies between two test methods:
you have to use an intermediate static value
as Cedric suggests, use TestNG, which specifically supports dependencies
in this case, you can create a method to create the line, and call it from both methods.
I would personally prefer 3, because:
I get independent tests, and I can run just the second test (in Eclipse or such like)
In my teardown in the class, I can remove the line from the database, the cleanup. This means that whichever test I run, I always start off with the same (known) database state.
However, if your setup is really expensive, you can consider this to be an integration test and just accept the dependency, to save time.
You should use TestNG if you need this (and I agree it's fairly common in integration testing). TestNG uses the same instance to run your tests, so values stored in fields are preserved between tests, which is very useful when your objects are expensive to create (JUnit forces you to use statics to achieve the same effect, which should be avoided).
First off, make sure your #Test 's run in some kind of defined order
i.e. #FixMethodOrder(MethodSorters.NAME_ASCENDING)
In the example below, I'm assuming that test2 will run after test1
To share a variable between them, use a ThreadLocal (from java.lang).
Note that the scope of the ThreadLocal variable is to the thread, so if you are running multiple threads, each will have a copy of 'email' (the static in this case implies that its only global to the thread)
private static ThreadLocal<String> email = new ThreadLocal<String>();
#Test
public void test1 {
email.set("hchan#apache.org);
}
#Test
public void test2 {
System.out.println(email.get());
}
You should not do that. Tests are supposed to be able to run in random order. If you want to test things that depend on one value in the database, you can do that in the #Before code, so it's not all repeated for each test case.
I have found nice solution, just add Before annotation to the previous test!
private static String email = null;
#Before
#Test
public void test1 {
email = "test#google.com"
}
#Test
public void test2 {
System.out.println(email);
}
If you, like me, googled until here and the answer didn't serve to you, I'll just leave this: Use #BeforeEach