I've created a simple test class with two fields like
#Mock
private MyTestClass myTestClass;
#Spy
private final MyContext context = CommonTestData.getDefaultContext();
Basically I don't really need the spy functionality here, it is just used to automatically inject the object into other mocks.
For the test, I tried to configure myTestClass like this:
when(myTestClass.someMethod(eq(context))).thenReturn(someValue);
The problem now is, that Matchers.eq is not matching "un-enhanced" versions of MyContext. So when someMethod is called during the test with a "regular" instance of MyContext that actually equals the value used for context, the stubbed method is not called.
It seems like the Mockito enhanced MyContext class implements its own equals method, at least the equals method of MyContext never seems to be called. Thus, I currently can't think of any way to modify the actual comparison being done.
I can think of various workarounds for this issue like using a custom argument matcher or stubbing the method with an instance of the "real" object. I was however wondering: Is there any Mockito-provided solution to check for equality of enhanced classes against their regular counterparts?
This is conceptually wrong: the idea of equals() in Java is to be symmetric: when a.equals(b) then you better find that b.equals(a), too!
And in your case, a has class MyContext, and b has WhateverMockitoSpyDoesToMyContext. So even when the equals() of the mockito generated thing works, most likely the other way round, that "base" equals might return false (because the original MyContext class knows nothing about potential subclasses like what Mockito is doing here).
I agree that it might be convenient to have your example work out, but I am simply not aware of a "correct" way getting there. From that point of view, you actually have to look into use an ArgumentMatcher.
Beyond that: seriously consider if you really gain anything by using eq() in the first place. If that check is the "core" of your test, then sure, somehow you better look for clear ways to have that check. But if it is more of a byproduct: then just use any() instead.
Meaning: don't make your tests more complicated than necessary. Normally, you setup things for one specific case anyway. You only have to worry about things passed to someMethod() if your code under test could actually, correctly pass different objects to that method.
Related
What is the best practice for verifying a method call with complex parameters when unit testing?
Say I'm testing a function like this:
class ClassA {
ClassB dependency;
void someFunction(SomeInputForA input) {
// do some thing
dependency.anotherFunction(differentInput);
}
}
The two options that I can think of for verifying that someFunction calls anotherFunction with the proper input are:
A) do a verify on the mock of dependency for calling anotherFunction
unitUnderTest.dependency = mockClassB;
InputClass expectedDifferentInput = ... ;
verify(mockClassB).anotherFunction(expectedDifferentInput);
B) do an argument captor on the call of anotherFunction and assert the properties
unitUnderTest.dependency = mockClassB;
ArgumentCaptor<InputClass> captor = ArgumentCaptor.for(InputClass.class);
verify(mockClassB).anotherFunction(captor.capture());
InputClass capturedInput = captor.getValue();
assertEquals(value, capturedInput.param1);
// and more asserts afterwards
Is there a suggested path here? I'd lean towards the captor method because it feels more rigorous and is not relying on objects equals implementations being proper.
Thoughts?
Is differentInput computated off input?
If so then your B) is the better way to go as you are saying for Input A, you expect ClassA to change this to expectedDifferentInput and want to verify the delegating class (ClassB) is called. You are verifying the transformation of the input and delegating logic of ClassA.
If differentInput has no relation to input then you don't need to use the captor as really you are just checking delegation.
Any public caller to someFunction on ClassA shouldn't need to know about ClassB so it can be said both methods A) and B) are actually white box testing, in this case and so you might as well use the captors anyway. As you vary your input to someFunction, captors may also help you to identify edge cases if differentInput is computed off input.
You can always use matchers on the object passed into mockClassB.anotherFunction(). For example, if you want to compare fields on an object, you can write:
Matcher<YourClass> yourMatcher = Matchers.hasProperty("yourProperty", Matchers.equals(whatever));
verify(mockClassB).anotherFunction(argThat(yourMatcher));
I prefer this way, since you can share syntax for the when and the verify for the matchers and you can combine any combination of matchers. You just need to include the latest mockito and hamcrest libraries to get this to work.
I've used argument captors but VERY sparingly. The biggest issue you run into is that this route creates fragile unit tests. And no one is happy when they make a small change to a class and then find themselves struggling with unit tests in calling classes that shouldn't have been affected.
That being said, absolutely you have to eventually ensure that correct calls are made. But if you rely on an equals override working, then you are relying on that class having an equals method that works, and this is then part of that class's contract (and unit tested in that class) which is reasonable.
So that's why I'd vote for keeping it simple and just using verify. Same thing in the end, but your unit test is just less fragile.
I want to create a new assertEquals which takes in as input a custom pojo for expected and actual.
How would I go about extending assertEquals of the JUnit library?
What I could do is implement a compare method which returns a boolean and have this as the input to the assertEquals or even assertTrue but creating my own assertEquals seems more elegant.
Would it simply be the case of returning true if equal or raising a AssertionError?
As #Makoto commented, you could use a custom Hamcrest Matcher.
The disadvantage of the other common answer here (just change the definition of Object#equals for your class), is that you would have one and only one way of comparing your objects, and it would have to match exactly what is needed by the test rather than what would be needed by users of the class. The two needs may or may not be identical. Often in testing, I only need to assert one or two values, sometimes several, but usually not what gets tested by the "natural" #equals method of my class. Furthermore, I work with a lot of classes that don't even have an explicit override of #equals. In these cases you would have to define one that works simply for the case of your test, whereas it semantically might not represent the domain very well.
There is an overload of assertEquals that takes objects. It (eventually) calls the equals method on both objects. So, the "compare" method you need to write is an override of Object's equals method.
Once you have that written, then you can call assertEquals("Failure message", yourObject1, yourObject2). There is no need to extend JUnit for this case.
As an aside, if you override equals, then you should override hashCode also, in a consistent way.
Asserts are static methods, defined in Assert class. TestCase derives from that class, hence all asserts are available there too.
java.lang.Object
|
+--junit.framework.Assert
|
+--junit.framework.TestCase
Creating another derived class, such as class MyTestCase extends TestCase and define your customized asserts there the same way they are defined in Assert.
Use MyTestCase instead of TestCase
Profit!
Another approach is to define proper equals() method and use standard assertEquals(). You can use EqualsBuilder to get a reasonable implementation automagically using reflection.
http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/EqualsBuilder.html
If you don't like Apache Commons, you can find similar tool in Guava.
I am currently in the process of using Mockito to mock my service layer objects in a Spring MVC application in which I want to test my Controller methods. However, as I have been reading on the specifics of Mockito, I have found that the methods doReturn(...).when(...) is equivalent to when(...).thenReturn(...). So, my question is what is the point of having two methods that do the same thing or what is the subtle difference between doReturn(...).when(...) and when(...).thenReturn(...)?
Any help would be appreciated.
The two syntaxes for stubbing are roughly equivalent. However, you can always use doReturn/when for stubbing; but there are cases where you can't use when/thenReturn. Stubbing void methods is one such. Others include use with Mockito spies, and stubbing the same method more than once.
One thing that when/thenReturn gives you, that doReturn/when doesn't, is type-checking of the value that you're returning, at compile time. However, I believe this is of almost no value - if you've got the type wrong, you'll find out as soon as you run your test.
I strongly recommend only using doReturn/when. There is no point in learning two syntaxes when one will do.
You may wish to refer to my answer at Forming Mockito "grammars" - a more detailed answer to a very closely related question.
Both approaches behave differently if you use a spied object (annotated with #Spy) instead of a mock (annotated with #Mock):
when(...) thenReturn(...) makes a real method call just before the specified value will be returned. So if the called method throws an Exception you have to deal with it / mock it etc. Of course you still get your result (what you define in thenReturn(...))
doReturn(...) when(...) does not call the method at all.
Example:
public class MyClass {
protected String methodToBeTested() {
return anotherMethodInClass();
}
protected String anotherMethodInClass() {
throw new NullPointerException();
}
}
Test:
#Spy
private MyClass myClass;
// ...
// would work fine
doReturn("test").when(myClass).anotherMethodInClass();
// would throw a NullPointerException
when(myClass.anotherMethodInClass()).thenReturn("test");
The Mockito javadoc seems to tell why use doReturn() instead of when()
Use doReturn() in those rare occasions when you cannot use Mockito.when(Object).
Beware that Mockito.when(Object) is always recommended for stubbing
because it is argument type-safe and more readable (especially when
stubbing consecutive calls).
Here are those rare occasions when doReturn() comes handy:
1. When spying real objects and calling real methods on a spy brings side
effects
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);
2. Overriding a previous exception-stubbing:
when(mock.foo()).thenThrow(new RuntimeException());
//Impossible: the exception-stubbed foo() method is called so
RuntimeException is thrown. when(mock.foo()).thenReturn("bar");
//You have to use doReturn() for stubbing:
doReturn("bar").when(mock).foo(); Above scenarios shows a tradeoff
of Mockito's elegant syntax. Note that the scenarios are very rare,
though. Spying should be sporadic and overriding exception-stubbing is
very rare. Not to mention that in general overridding stubbing is a
potential code smell that points out too much stubbing.
Continuing this answer, There is another difference that if you want your method to return different values for example when it is first time called, second time called etc then you can pass values so for example...
PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class));
So it will return false when the method is called in same test case and then it will return false again and lastly true.
The latter alternative is used for methods on mocks that return void.
Please have a look, for example, here:
How to make mock to void methods with mockito
Perhaps I have completely fallen short in my search, but I cannot locate any documentation or discussions related to how to write a unit test for a Java class/method that in turn calls other non-private methods. Seemingly, Mockito takes the position that there is perhaps something wrong with the design (not truly OO) if a spy has to be used in order to test a method where mocking internal method calls is necessary. I'm not certain this is always true. But using a spy seems to be the only way to accomplish this. For example, why could you not have a "wrapper" style method that in turn relies on other methods for primitive functionality but additionally provides functionality, error handling, logging, or different branches dependent on results of the other methods, etc.?
So my question is two-fold:
Is it poorly designed and implemented code to have a method that internally calls other methods?
What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?
This might be a difficult request, but I would prefer for those who decide to answer to not merely re-publish the Mockito verbiage and/or stance on spies as I already am aware of that approach and ideology. Also, I've used Powermockito as well. To me, the issue here is that Mockito developed this framework where additional workarounds had to be created to support this need. So I suppose the question I am wanting an answer to is if spies are "bad", and Powermockito were not available, how is one supposed to unit test a method that calls other non-private methods?
Is it poorly designed and implemented code to have a method that internally calls other methods?
Not really. But I'd say that, in this situation, the method that calls the others should be tested as if the others where not already tested separately.
That is, it protects you from situations where your public methods stops calling the other ones without you noticing it.
Yes, it makes for (sometimes) a lot of test code. I believe that this is the point: the pain in writing the tests is a good clue that you might want to consider extracting those sub-methods into a separate class.
If I can live with those tests, then I consider that the sub-methods are not to be extracted yet.
What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?
I'd do something like that:
public class Blah {
public int publicMethod() {
return innerMethod();
}
int innerMethod() {
return 0;
}
}
public class BlahTest {
#Test
public void blah() throws Exception {
Blah spy = spy(new Blah());
doReturn(1).when(spy).innerMethod();
assertThat(spy.publicMethod()).isEqualTo(1);
}
}
To me, this question relates strongly to the concept of cohesion.
My answer would be:
It is ok to have methods (public) that call other methods (private) in a class, in fact very often that is what I think of as good code. There is a caveat to this however in that your class should still be strongly cohesive. To me that means the 'state' of your class should be well defined, and the methods (think behaviours) of your class should be involved in changing your classes state in predictable ways.
Is this the case with what you are trying to test? If not, you may be looking at one class when you should be looking at two (or more).
What are the state variables of the class you're trying to test?
You might find that after considering the answers to these types of questions, your code becomes much easier to test in the way you think it should be.
If you really need (or want) to avoid calling the lower-level methods again, you can stub them out instead of mocking them. For example, if method A calls B and C, you can do this:
MyClass classUnderTest = new MyClass() {
#Override
public boolean B() {return true;}
#Override
public int C() {return 0;}
};
doOtherCommonSetUp(classUnderTest);
String result = classUnderTest.A("whatever");
assertEquals("whatIWant", result);
I've used this quite a quite a bit with legacy code where extensive refactoring could easily lead to the software version of shipwright's disease: Isolate something difficult to test into a small method, and then stub that out.
But if the methods being called are fairly innocuous and don't requiring mocking, I just let them be called again without worrying that I am covering every path within them.
The real question should be:
What do I really want to test?
And actually the answer should be:
The behaviour of my object in response to outside changes
That is, depending on the way one can interact with your object, you want to test every possible single scenario in a single test. This way, you can make sure that your class reacts according to your expectations depending on the scenario you're providing your test with.
Is it poorly designed and implemented code to have a method that internally calls other methods?
Not really, and really not! These so called private methods that are called from public members are namely helper methods. It is totally correct to have helper methods!
Helper methods are there to help break some more complex behaviours into smaller pieces of reusable code from within the class itself. Only it knows how it should behave and return the state accordingly through the public members of your class.
It is unrare to see a class with helper methods and normally they are necessary to adopt an internal behaviour for which the class shouldn't react from the outside world.
What is the best practice and/or approach in writing a unit test for such a method (assuming it is itself a good idea) if one has chosen Mockito as their mocking framework?
In my humble opinion, you don't test those methods. They get tested when the public members are tested through the state that you expect out of your object upon a public member call. For example, using the MVP pattern, if you want to test user authentication, you shall not test every private methods, since private methods might as well call other public methods from an object on which depend the object under test and so forth. Instead, testing your view:
#TestFixture
public class TestView {
#Test
public void test() {
// arrange
string expected = "Invalid login or password";
string login = "SomeLogin";
string password = "SomePassword";
// act
viewUnderTest.Connect(login, password);
string actual = viewUnderTest.getErrorMessage;
// assert
assertEqual(expected, actual);
}
}
This test method describes the expected behaviour of your view once the, let's say, connectButton is clicked. If the ErrorMessage property doesn't contain the expected value, this means that either your view or presenter doesn't behave as expected. You might check whether the presenter subscribed to your view's Connect event, or if your presenter sets the right error message, etc.
The fact is that you never need to test whatever is going on in your private methods, as you shall adjust and bring corrections on debug, which in turn causes you to test the behaviour of your internal methods simultaneously, but no special test method should be written expressly for those helper method.
I'm using easymock, and I am mocking my UserService class.
My UserService has a few methods:
boolean canUserLogin(..);
boolean canUserJoinClass(...);
Now some of the methods call each other, and if I am testing method#1 I want to stub/mock methods #2 and methods# 3 that are called in method#1.
What I am confused is, how can I mock parts of a class and leave others to run the actual code?
So I want to actually test UserService.method#1, but mock UserService.method#2 and UserService.method#3 that method#1 calls internally.
By specifying return values for the methods you want mocked; see the easymock docs for examples.
The "Specifying Return Values" section discusses creating return values for mocked methods.
The "Partial mocking" section (towards the bottom) discusses mocking actual classes.
I agree with the docs (and other answers) that this may be an indication of sketchy design. Without further details, it's hard to say how sketchy it is, if it is at all.
You can check some library like Easymock, but I don't sure whether it can do this.
And here is my solution without third-party library. Create a subclass of UserService, and override the method you want to mock.
class SubUserService{
#override
boolean canUserJoinClass(...){
return false;
}
}
But notice the mock method can't be private.
And if this is one real problem you meet, you should refactor you methods to different classes.
I know Mockito supports "spy" on real objects. I could not find an equivalent in Easy Mock. So, I am not sure if you can do this.
Having said that, this is a smell to me. Why do you need to mock it? Is that an indication of the fact that your object is doing too much and hence you need to mock the other interactions?
Also, whenever you need to worry about the implementation of a method (method 1 in this case) i.e. the fact that it calls method2 and method3, especially of the same class, that sounds to me like a encapsulation leaking.
Mocking is intended to be used for dependencies, so you can test in isolation. In this case, you don't have any dependencies, since the methods you are calling are on one class. So I wouldn't use mocking here.
If methods 2 and 3 are so complicated that you want to mock them when testing method 1, then perhaps you should separate them out into their own class(es), so you can easily mock them.