I want to ask more of a conceptual question related to testing. I am using Mockitos for my unit testing.
I have a method that does bunch of things. All the methods it calls internally are void methods, which in turn will do some other actions. The method under question can complete with exception or without exception. There is no scope for writing assert statements as it mostly calls void methods. Also, I have written independent unit test for all other methods of this class.
My question is if I need test coverage, I should write test case for all methods. But, I do not find any valid assert for one of my method. The method under question is an important method from unit test coverage perspective. When I run my test, I do see in logs that the methods executes fine but there is really nothing to assert. What should I do in such a situation?
1) Leave the method as is without any asserts? It still is checking if everything is working as expected
2) Create 2 methods one that expects exception ( Negative Testcase) and one regular test method with no asserts. ( This is to basically show I have covered both positive and negetive scenario). I still do not have any asserts here.
Is this the right approach to take or there is a better way for dealing with this problem?
If you don't have anything worth asserting, you can try verification instead.
verify(someMock, times(x)).someMethod();
More on verification with Mockito in the documentation: https://mockito.googlecode.com/hg-history/1.5/javadoc/org/mockito/Mockito.html
Why isn't there anything to assert? Let A be the universe if you run your method. Let B be the universe if you don't run your method. If A == B then stop calling the method, it's not doing anything. If A != B then assert that whatever is different about them is true.
i.e., what is your method actually doing? That should be part of your test.
Related
When I write Unit Test, sometimes I faced situations as shown below. There is a method createOrUpdate that calls another methods based on a condition. In this scene, I have 2 options:
1. I can write a test for all of 3 methods and in the first test method (createOrUpdate), just verify if the other methods (create or update) is called. In the other test methods, I write test as usually written.
2. I can write multiple tests just for the first method (createOrUpdate) and test the other 2 methods based on the condition. Then I think I could test all of these 3 methods.
As I am new in Unit Testing, I just wanted to be clarified which approach is a proper or suitable approach for Unit Testing. Any help would be appreciated.
countryService:
public CountryDTO createOrUpdate(UUID uuid) {
if (countryRepository.existsByUuid())
return update(uuid);
else
return create(uuid);
}
public CountryDTO create(UUID uuid) {
// ...
}
public CountryDTO update(UUID uuid) {
// ...
}
This actually depends on your implementation of functions.
In case #create and #update functions are only getting called from #createOrUpdate function, then second appraoch (just writting the tests for #createOrUpdate function) makes much more sense.
In case #create and #update functions can be accessed by external classes/functions as well, then the first approach (writting tests for individual) makes more sense. Since you can send different types of data to the function directly, allowing you to cover all the ground properly. E.g.: You can test out what will happen when UUID is not present and someone is calling your #update function.
Overall, you can use both of these approach till your are covering all the cases properly.
Apologies for long answer:
First you need to understand why we write Junit test cases.
The main reason is to make sure our public methods behaves as expected for all possible input combinations for the users of that method, so each public method need to have their own test cases to assert the behavior of that method, Test case of one method should not know if any other method which is using it is also having test cases
Lets understand Why and How:
Assume if you go with your 1st approach -
I can write a test for all of 3 methods and in the first test method (createOrUpdate), just verify if the other methods (create or update) is called. In the other test methods, I write test as usually written.
Let's think from the point of view of the users of method createOrUpdate
what if tomorrow someone makes any changes in method 2, and method 3, they will just update the test case for those 2 methods and you the test case of method 1 won't identify the change in behavior of method 1 which is a bug for users of method 1
So to avoid such future bugs you need to write test case to assert the behavior of the methods, not just if the method is calling some others method or not
Now assume if you go with your 2nd approach -
I can write multiple tests just for the first method (createOrUpdate) and test the other 2 methods based on the condition. Then I think I could test all of these 3 methods.
Let's think from the point of view of the users of method create and update -
what if in your current code of first method (createOrUpdate) you need some extra behavior, and you go ahead and update the internal called methods(2, 3) instead of writing new code in method 1 ??
..You will fulfill the future needs of method 1, and update test cases of method 1 only, but as there are no separate test cases for method 2, method 3 you won't know if you have broken needs of method 2, method 3 users!!
Which can create bug for users of method 2, and method 3!!
So to avoid such future bugs you need to write test case to assert the behavior of each method separately, if if you find some test logic redundant in multiple test cases
When writing test cases the usual pattern is setup > execute > verify. This results in unit tests that look like this:
#Test
void testSomething() {
// Setup
when(someMock.someMethod()).thenReturn("someValue");
// Execute (the doSomething implementation would invoke someMock.someMethod)
testee.doSomething();
// Verify
verify(someMock, times(1)).someMethod();
}
My question is, is it necessary to include the verify call considering the when call will raise a UnnecessaryStubbingException exception?
This question only applies in cases where times is 1 since the absence of UnnecessaryStubbingException only implies that someMethod has been called once and with the correct arguments and there may be cases where you want to verify that someMethod has been called never. Without the verify the test would look like this and achieve the same checks:
#Test
void testSomething() {
// Setup
when(someMock.someMethod()).thenReturn("someValue");
// Execute (the doSomething implementation would invoke someMock.someMethod)
testee.doSomething();
}
Edit: A friend pointed out that verifyNoMoreInteractions relies on you having verify calls so I guess this is important to consider.
Edit 2: I've changed "necessary" to "preferred" in the title since I'm more interested in the pros/cons of each approach versus what is technically required.
Thanks in advance!
It is not necessary, as you mentioned - technically test validates this behavior. So the choice should go from preferences and expertise of your team. I personally think having explicit verification step makes your test more readable and maintainable. Few reasons:
You can have more when invocations, not relevant to verification logic, this will "hide" the test intention, e.g.
#Test
void testSomething() {
// Setup
when(someMock.someMethod()).thenReturn("someValue");
when(someMock2.someMethod2()).thenReturn("someValue2");
when(someMock3.someMethod3()).thenReturn("someValue3");
// Execute (the doSomething implementation
// would invoke someMock.someMethod)
testee.doSomething();
// code reviewer - "hm? what do we really test here?"
}
From API perspective throwing of exception in UnnecessaryStubbingException in when is not obvious - this can bring a confusion for occasional code reader who missed that fact. Having verify makes the intention of test clear for almost any developer, even coming from other tech stack
Some developers can come from earlier Mockito versions where throwing of UnnecessaryStubbingException was not the case
UnnecessaryStubbingException is only raised when Mockito is in strict mode. If this setting is changed to lenient down the line you'd no longer be able to rely on this exception being raised.
You can create scenarios where not including verify calls means subsequent verifyNoMoreInteractions calls will fail.
If you're already aware that your piece of code will throw an exception, its better to have a test case covering it like below
#Test(expected = UnnecessaryStubbingException.class)
A test case(the one you have shown skipping verify) without any assertion or verify statement has no meaning in it. It's a good approach to have verify check for cases when methods have void return type.
No, It is not necessary to add Verify for each when call in Mockito. Every testcase should be deterministic in nature.
To answer your question the preferred way is to use in this particular case is to verifyNoMoreInteractions or verify(somemock, never()).someMethod()
It is not necessary that you always need verify. You can use assertions as well. But, A testcase must have either of them.
For Eg. If you are sure that some method is going to throw an Exception.
#Test(expected = HeyIAmException.class)
void testSomething() {
classUnderTest.someMethodWhichThrowsException();
}
or In Junit 5.
#Test
void testSomething() {
when(someMock.someMethod()).thenReturn("someValue");
HeyIAmException exception = assertThrows(HeyIAmException.class, () ->
classUnderTest.someMethodWhichThrowsException()
);
assertEquals(exception.getCode(),rightCode);
}
In your approach addition to Udalmik's answer I have following more lines to add.
We will never know which stub method have caused exception, as any of the someMethod could throw the exception.
The intention of the test is not very clear.
Imagine you have method someMethod, how would you go by to test it?
Mockito.when(someClass.someMethod(someParam)).thenReturn(someValue);
var bar = foo() // SUT: ends upp calling someMethod somewhere in the stack
assertThat(bar).isEqualTo(someValue);
vs
Mockito.when(someClass.someMethod(someParam)).thenReturn(someValue);
var bar = foo() // SUT: ends upp calling someMethod somewhere in the stack
verify(someClass, times(1)).someMethod(someParam)
assertThat(bar).isEqualTo(someValue);
It is true that the Mockito.when is "kind of" verifying that someClass.someMethod is being called with the correct arguments. Personally I like the idea of having clear assertions/verifications so that the tests can serve as a form of documentation. I don't like giving my mocks double-responsibilities, I want to keep my mocks just simply as "mocks".
So back to my question.
What is the preferred way, using Mockito.when combined with Mockito.verify or only Mockito.when?
When defines the behaviour of the Mock - declaratively defining the way the mock will respond when methods are invoked with different parameters.
Verify is used to check whether the Mock has been interacted with in various ways.
Here are some URLS to the official Mockito documentation, which I hope will help.
Stubbing - with when
Argument matchers
Verification in order
Making sure interaction(s) never happened
on mock
It's probably worth performing a search for some other examples.
I think this question has been answered in https://stackoverflow.com/a/35301264/473064.
The summary is:
In short, it is considered good Mockito style to explicitly verify only the interactions that can't be implied from well-crafted stubs and postcondition assertions. They may be good calls for otherwise-unmeasurable side effects—logging code, thread executors, ArgumentCaptors, multiple method calls, callback functions—but generally should not be applied to stubbed interactions.
One point that I would add is that sometimes if we want to do a verifyZeroInterations to ensure that no unexpected calls occurred, we would have to first exhaust the known calls by verifying them.
What I usually do is to perform the simplest verify(mock, times(n)).someMethod(anyClass()) as generally as possible without repeating the more specific argument matching that I have already specified in the stubbing, which reduces the duplication as much as possible.
Example:
when(someObject.someMethod(eq("abc"))).thenReturn(someValue);
when(someObject.someMethod(eq("def"))).thenReturn(otherValue);
when(someObject.someMethod(endsWith("suffix"))).thenReturn(anotherValue);
var bar = foo();
assertEquals(expectedBar, bar);
verify(someObject, times(3)).someMethod(anyString());
verifyZeroInteractions(someObject);
Regarding your concern in the comment:
The problem I see is, if a new developer reads the test, they won't know the subbed method is part of the verification process.
The stubbed method is not part of the verification process. It's part of the test case setup, i.e., the Given step.
I think your example might be a little bit misleading. The final output from foo() is usually a transformation of the response from someMethod, i.e., someValue in the example. So if the stubbed method is not called and returned with the correct value, the test would have failed anyway. The said developer would then have to look at the mocking and understand how the test case works.
In the updated example below, there is no need to verify that someMethod is called because if it didn't get called, the assertion would fail.
Mockito.when(someClass.someMethod(someParam)).thenReturn(someValue);
var bar = foo() // SUT: ends upp calling someMethod somewhere in the stack
var expectedValue = // a value depending on `someValue`
assertThat(bar).isEqualTo(expectedValue);
I always have the doubt if unit testing isolation should be done at very fine grain like stubbing internal method calls, look at the following example with Java, JUnit and Mockito.
package com.company.domain;
public class Foo {
private FooHelper helper;
public setHelper(FooHelper helper) {
this.helper = helper;
}
public Double method1(Integer a, Integer b) {
... // logic here
Integer var = method2(a); // internal call to method2
... // more logic here
}
protected Integer method2(Integer c) {
... // logic here and return an Integer
}
}
This is the test class:
package com.company.domain;
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
#Mock private FooHelper fooHelperMock; // mocking dependencies as usual
#InjectMocks #Spy Foo foo; // this way we can stub internal calls
#Test
public void method1Test() {
doReturn(2).when(foo).method2(1); //stub the internal method call
... // stub fooHelperMock method calls here
Double result = foo.method1(1, 2);
assertEquals(new Double(1.54), result);
verify(foo, times(1)).method2(1);
... // verify fooHelperMock method calls here
}
#Test
public void method2Test() {
... // stub fooHelper method calls here
assertEquals(new Integer(5), foo.method2(3));
... // verify fooHelperMock method calls here
}
}
I think this way you are able to really isolate the code under testing at method level even with internal calls. But I cannot find lot of information about this being considered a good practice or not and why.
In general, testing a class's internal function calls makes your tests far too fragile. When unit testing, you only want to see that the class as a whole is doing what it is supposed to do. You are supposed to intentionally ignore the internals.
Ignoring the internals has a lot of useful benefits. Mainly, if you change the methods -- as long as the public interface stays the same -- your tests will all still pass. Yay. This is the type of stability you want your unit tests to have. Fragile unit tests are almost worse than no unit tests. A fragile test has to be changed every time the code changes even if everything is still working. That provides you with nothing but extra work.
There are exceptions though. I would consider mocking out internal function calls in the following cases:
1) The internal call pulls data from somewhere. For example a database or large file. This is often called a 'boundary' test. We don't want to really set up a database or file to test, so instead we just sub out the function. However, if you find yourself doing this, it probably means that your class should be split into two classes because it is doing too many different things. Make yourself a dedicated database class instead.
2) The internal call does heavy processing that takes a lot of time. In that case, it might make sense to sub out the function instead of waiting. However, once again this might be a sign that you're on the wrong track. You should try to find a way to make things more partitioned so no single step takes that long.
In conclusion, I would highly recommend you do not test at the method level. A class should be a distinct unit. If the class is working everything is fine. This approach give you the testing you need to be secure and the flexibility you need to change things.
#raspacorp
Indeed, if you only test one case, someone could hardcode var = 2 and then pass your test case. But it is your job in designing tests cases to cover enough different cases to be reasonably satisfied that it is behaving appropriately.
As far as tests changing because the code has changed, this is not what you want at all. You want your tests to verify that the responses you are getting are correct for all the different types of cases. As long as the responses are correct, you want to be able to change everything without changing the tests at all.
Imagine a large system with thousands of tests verifing that everything is working right. Now imagine that you want to make a HUGE optimization change that will make things go faster, but change how everything is stored and calculated. What you want your tests to allow you to do is only change code (not tests) and have the tests continually confirm that everything is still working. This is what unit tests are for, not catching every possible line change, but rather to verify that all the calculations and behaviors are corrent.
This article from Martin Fowler answers your question.
You're a mockist, as I'm, but there are many people who don't like this approach and prefer the classicist approach (e.g. Kent Beck).
Roy Osherove says that the goal of a test, when it fails, is to identify the production code causing the problem, and having that in mind is obvious that the more fine grained the better.
For sure being a mockist may be overwhelming for beginners, but once you're used to the mechanisms of a Mocking library the benefits are uncountable while the effort is not much higher than the other approach.
I do not think it is necessary and I would even go further to say you should not do this. You are writing more test code to test less of you application code. In general it is considered good practice to only test public methods, because a unit test should only be concerned whether a method under test satisfies its contract (i.e. does what it is supposed to do) and not how the method is implemented. If you have a bug in your private method, how will you know?
Mockito seems like a pretty sweet stubbing/mocking framework for Java. The only problem is I can't find any concrete documentation on the best ways of using their API. Common methods used in tests include:
doXXX(???) : Stubber
when(T) : OngoingStubbing
then(T) : OngoingStubbing
verify(???) : T
given(T) : BDDOngoingStubbing
willXXX(???) : BDDStubber
When you see examples of Mockito in practice, you see code like:
when(yourMethod()).thenReturn(5);
From all the docs I've read, I've identified several "patterns" of Mockito "grammars" obtained from daisy-chaining these method calls together like the example above. Some common patterns I've found are:
When/Then: when(yourMethod()).thenReturn(5);
Given/Will: given(yourMethod()).willThrow(OutOfMemoryException.class);
Do/When: doReturn(7).when(yourMock.fizzBuzz());
Will/Given/Do: willReturn(any()).given(yourMethod()).doNothing();
Verify/Do: verify(yourMethod()).doThrow(SomeException.class);
What I'm choking on is how to select the right pattern/combination of method calls to model my test cases. It seems like you can daisy-chain these together in seemingly endless combos and I'm not sure what pattern is right for which problem.
Can some Mockito Guru help shed some light as to which patterns/combinations of Mockito methods are used for which types of test cases (and why)? Thanks in advance!
There are several disadvantages to the when/thenReturn, when/thenThrow and when/then syntaxes. For example,
In the case of when/thenReturn, if the return type is a generic with a
wildcard, and you wish to return a mock of the same type, you will be unable
to avoid a compile warning.
You can't use when/thenThrow and when/then for a void method.
You can't use these syntaxes on Mockito spies.
You can only call when once for each combination of mock object,
method and arguments, unless you call reset on the mock.
Calling when multiple times for one combination of mock
object and method, when you are using argument matchers, can lead to problems.
I find these cases difficult to remember. So instead of trying to keep track of when the
when/thenReturn, when/thenThrow and when/then syntaxes will and won't work, I prefer to avoid them completely, in favour of the doReturn/when, doThrow/when and doAnswer/when alternatives. That is to say, since you'll occasionally need doReturn/when, doThrow/when and doAnswer/when, and you can ALWAYS use these methods, there is no point in learning how to use when/thenReturn, when/thenThrow and when/then.
Note that doReturn, doThrow and doAnswer can be chained together in the same way as thenReturn, thenThrow and then. What they don't have is an option for returning several values (or throwing several exceptions, or running several answers) within a single call to doReturn, doThrow and doAnswer. But I find that I need to do this so seldom, that it doesn't really matter.
There's one more disadvantage to doReturn, which I consider insignificant. You don't get compile time checking of the type of its argument, like you do with when/thenReturn. So if you get the argument type wrong, you won't find out until you run your test. Frankly, I don't care.
In summary then, I have been using Mockito for more than two years, and I consider the consistent use of doReturn, doThrow and doAnswer to be a Mockito best practice. Other Mockito users disagree.
Mockito often have several ways of doing things.
I find myself using mostly:
// Setup expectations
when(object.method()).thenReturn(value);
when(object.method()).thenThrow(exception);
doThrow(exception).when(object.voidMethod());
// verify things
verify(object, times(2)).method();
verify(object, times(1)).voidMethod();
I've found that i can do 95% of what i need to with these three kinds of calls.
Also, what version of Mockito are you using? "given" and "will" constructs are not present in the latest version (1.9.0+)
However, there are cases where I want the return value or exception to respond to the input. In this case, you can use the Answer interface to inspect the method arguments and return an appropriate value.
public class ReturnFirstArg<T> implements Answer<T> {
public T answer(InvocationOnMock invocation) {
return invocation.getArguments()[0];
}
}
when(object.method(7)).thenAnswer(new ReturnFirstArg<Integer>());
The things in fact looks much simpler than you thought
REF: http://static.javadoc.io/org.mockito/mockito-core/2.7.12/org/mockito/Mockito.html
Verify:
In order to use Mockito, you need to understand one basic philosophy of Mockito: Stubbing and Verification is separated. Therefore, the "Verify/Do" you mentioned is in fact doing the "Verification" job, while the other 4 "grammars" is for stubbing. Stubbing define how the mock object will react in different situation. Verification is to make sure what the mocks is invoked as expected, in previous invocation to system under test (SUT).
When/Then , Given/Will:
Then it come to the "When" and "Given" families. You can simply treat them as aliases of each other. "Given" family is added in Mockito 1.8.x as to make it looks more aligned to BDD practices.
DoXxx:
In normal case we mostly use when(xxx).then(...) (and given(...).will(...) ) . However there are some case that syntax is not working. The most obvious case is when return type of the stubbed method is void. In such case when(mockObj.voidMethod()).thenThrow(anException) is not going to compile. As a workaround, an alternative syntax of Do/When is created, so you can write the previous line as doThrow(anException).when(mockObj.voidMethod())