I'm using Junit in conjunction with Mockito. I used mockito's verify method + junit assertion to do complete verification. Is this not desirable? Should we use one or the other but not both?
There's nothing wrong with using both.
Mockito's verify is used to assert a method was called (with the expected arguments) on the given mock.
JUnit's assertXYZ is used to assert that some result has the expected value.
Both are valid verifications, and if both are relevant, both should be used.
For example, consider the following (admittedly artificial) situation:
You have an interface that performs some mathematical calculation:
public interface ValueProducer {
public int getValue(int val);
}
And a class that doubles any result produced by it:
public class Doubler {
public static int doubleThatResult (ValueProducer producer, int val) {
return 2 * producer.getValue(val);
}
}
Testing it would require to assert two things:
That getValue was properly called
That the result is doubled
So, e.g.:
public class DoublerTest {
#Test
public void testDoubleThatResult() throws Exception {
int value = 7; // Or any other value
int returnMock = 13; // Or any other value
ValueProducer producerMock = mock(ValueProducer.class);
when(producerMock.getValue(value)).thenReturn(returnMock);
int actual = Doubler.doubleThatResult(producerMock, value);
verify(producerMock);
assertEquals(26, actual);
}
}
Mureinik's answer is absolutely correct—assertions and verifications are complementary, and work quite well together—but doing both for a single behavior may be redundant.
The goal is usually to express the test in the most flexible and implementation-agnostic way possible. State testing (with assertions) is often the most appropriate choice, in that sense: it doesn't matter which methods were called as long as the resulting state is correct. A Mockito verification, while possible, may introduce brittleness (where the code behaves correctly but the test is broken). Mockito itself warns of this in verify(T)'s Javadoc and the linked article by Mockito's creator Szczepan Faber.
This redundancy is certainly not the worst thing: It does test a property of the system, and may be a worthwhile endeavor in testing interactions with sensitive, legacy, third-party, or frequently-changing dependencies. If the interaction is unimportant, though, these extra verifications may come at the expense of brittleness.
Other times, confirming correct behavior means testing side-effects—for example, ensuring that someSystem.reset() was called, or testing a cache by verifying a provider was NOT called. These are perfect examples for verification, because the interaction with the external service is critical testable behavior. In some of these cases, Mockito verifications are the only way to make the correct assertions.
Many test cases are a combination of the above, so feel free to use assertions and verifications freely together; just remember that state testing is often sufficient and preferable.
Related
I have a method called calculate
public class Calculator {
public void calc(int a, int b){
String condition = "first";
int result = 0;
if (condition.equals("first") {
condition = "no need";
else { result = a + b;}
after which the result is printed, whatever, i need to make a test on which i see if the value of condition was changed to "no need" or it remained "first", how can i check this using mockito testing? I tried so far, but i did not succeed. A good theoretical answer would be good, no need for code.
A good theoretical answer would be good
Mockito isn't a testing framework, it's a mocking framework.
You don't test things with Mockito, you just substitute behavior in dependencies, in order that you can test the behavior of your code under specific and otherwise hard-to-reproduce conditions.
So, the premise of the question is flawed, not simply because you're not using Mockito correctly, but also because you have no dependencies in this code for which behavior might be substituted.
But assuming you actually mean "how can I test this with a testing framework": you can't do that either.
Testing frameworks are just Java programs that run your Java program. They're not magic: all they can test for are return values, thrown exceptions, and side effects (e.g. log messages, things printed, changes of state).
The only things being changed here are local variables. You can't test anything about these because they are not observable outside the method in which they are defined.
I have the following method:
public < V extends U > boolean matchesObject (V object, String filter) {
if (filterIsAny(filter)) return true;
else {
List<T> targets = getFilterTarget(object);
for (T t : targets) if (matches(t, filter)) return true;
return false;
}
}
where filterIsAny(filter) is a trivial method (just checks filter != null).
My question is: when I'm unit testing, is it worth to mock this method so that I'm sure that my function follows the correct path in the function, or do I just assume that my filterIsAny(filter) works and test using the real method? In this particular case, it is pretty easy to mock this method, but I have other instances where it would take several lines of code to mock intermediate results returned by trivial functions, such as list.indexOf(object) in a list of mocked objects.
I know it wouldn't be "pure" unit testing, since theoretically I'd be testing more than one function at a time, but how is is worth doing pure unit testing when it takes more work than finding the error in the code in the case of the test failing?
Assume that filterIsAny works until it gains non-trivial logic.
If your function is a wrapper for a single pure Java statement which has no logical branches, you can safely skip writing a unit test for it, and therefore only it in other unit tests. What you do want to test are the various branches in the method to be tested, assuming it has non-trivial logic.
Here, you would setup your filter object such that it produces a true and a false result when testing matchesObject(V object, String filter) based on the logical branch you're testing (no match in collection, one match in collection, invalid collection type (if possible), null input, etc.)
In your case, you can skip the filterIsAny(filter) evaluating to true branch, since you execute a trivial statement return true afterwards.
By the way, consider refactoring to Stream.anyMatch() if possible; it will reduce the number of return statements in your function and enhance readability.
What is the way to test the methods when there are two public methods and a method calls another public method in the same class?
How should I write unit tests in this scenario?
An example
class SpecificIntMath {
public int add(int a,int b) {
return a+b;
}
public int multiply(int a, int b) {
int mul = 0;
for(int i = 0;i<b,i++) {
mul=add(a,mul);
}
return mul;
}
}
This example doesn't show the complexity of both the methods involved but the concept.
Should I test add and multiply separately? If I should test multiply only, I feel like we miss out cases where multiple cannot provide parameters.
Assuming multiply and add to be tested separately, should I be able to mock add? How is that possible?
Assuming multiply and add to be tested separately and I shouldn't mock, should I let add perform as it is. If this is the case how should I deal with the flow of the program inside add?
What is the approach to test such a kind of situation.
Edit 1:
In the below code,
class MCVC {
public boolean getWhereFrom(List<User> users) {
boolean allDone = true;
for(User user: users){
String url = user.getUrl();
switch(url) {
case Consts.GOOGLE:
someDao.updateFromAddr(user);
user.setEntry("Search Engine");
break;
case Consts.FACEBOOK:
someDao.updateFromAddr(user);
user.setEntry("Social Media");
break;
case Consts.HOME:
someDao.updateToAddr(user);
user.setEntry("Company");
default
user.setEntry(null);
allDone = false;
break;
}
}
return allDone;
}
public void likedDeck() {
List<Users> usersList = deckDao.getPotentialUsers(345L,HttpStatus.OK);
boolean flag = getWhereFrom(usersList);
if(flag) {
for(User user: usersList) {
//some Action
}
}
}
}
Should I consider getWhereFrom() while testing likedDeck() or should I assume any default situation? If I consider default situation, I lose out on cases where the output isn't default. I am not sure I should mock it since class which is calling is being tested. Spying/Mocking class under test
You don't care.
You use unit-testing to test the contract of each public method on its own. Thus you write tests that make sure that both add() and multiply() do what they are supposed to do.
The fact that the one uses the other internally is of no interest on the outside. Your tests should neither know nor care about this internal implementation detail.
And just for the record: as your code is written right now; you absolutely do not turn to mocking here. Mocking is not required here; and only adds the risk of testing something that has nothing to do with your real production code. You only use mocking for situations when you have to control aspects of objects in order to enable testing. But nothing in your example code needs mocking to be tested. And if it would - it would be an indication of poor design/implementation (given the contract of those methods)!
Edit; given the changes example in the question:
First of all, there is a bug in getWhereFrom() - you iterate a list; but you keep overwriting the return value in that list. So when the first iteration sets the result to false; that information might be lost in the next loop.
I see two options for the actual question:
You turn to Mockito; and its "spy" concept to do partial mocking; in case you want to keep your source code as is
Me, personally; I would rather invest time into improving the production code. It looks to me as getWhereFrom() could be worth its own class (where I would probably not have it work on a list of users; but just one user; that also helps with returning a single boolean value ;-). And when you do that, you can use dependency injection to acquire a (mocked) instance of that "WhereFromService" class.
In other words: the code you are showing could be reworked/refactored; for example to more clearly follow the SRP. But that is of course a larger undertaking; that you need to discuss with the people around you.
At least test them both seperatly. That the multiply test implicitly tests the add is no problem. In most of this cases you should ask yourself the question if it is necessary that both methods need to be public.
Should I test add and multiply separately?
You should test them separately, if you are doing unit testing. You would only like to test them together when doing component or integration tests.
Assuming multiply and add to be tested separately, should I be able to
mock add?
yes
How is that possible?
use mockito or any other mocking framework. Exactly how you can see here Use Mockito to mock some methods but not others
Assuming multiply and add to be tested separately and I shouldn't
mock, should I let add perform as it is.
I wouldn't do that. Internal changes in add could affect the tests from multiply and your tests would get more complicated and unstable.
#Test
public void onConnectionCompletedTest() {
connectionProvider.initialize();
connectionProvider.addEventObserver(SocketEvent.Type.SOCKET_CONNECT, mockedObserver);
connectionProvider.onConnectionCompleted(mockedChannel);
verify(mockedObserver).socketEventObserved(socketEventCaptor.capture());
Assert.assertEquals(SocketEvent.Type.SOCKET_CONNECT, socketEventCaptor.getValue().getType());
}
#Test
public void onConnectionClosedTest() {
connectionProvider.initialize();
connectionProvider.addEventObserver(SocketEvent.Type.SOCKET_DISCONNECT, mockedObserver);
connectionProvider.onConnectionClosed(mockedChannel);
verify(mockedObserver).socketEventObserved(socketEventCaptor.capture());
Assert.assertEquals(SocketEvent.Type.SOCKET_DISCONNECT, socketEventCaptor.getValue().getType());
}
The problem is when I run both of these tests, the 2nd one fails. But if I comment out
verify(mockedObserver).socketEventObserved(socketEventCaptor.capture());
Assert.assertEquals(SocketEvent.Type.SOCKET_CONNECT, socketEventCaptor.getValue().getType());
then the 2nd test will pass. There's a lot of different classes/methods involved in this so hopefully this is enough information to be able to come up with an explanation.
The error I get:
wanted but not invoked:
mockedObserver.socketEventObserved(
<Capturing argument>
);
-> at com.company.cnx.cip.io.ConnectionProviderTest.onConnectionClosedTest(ConnectionProviderTest.java:188)
Actually, there were zero interactions with this mock.
My question exactly: What could be happening that when I #Ignore the first test, the 2nd will pass?
EDIT: I have an #Before class that's important.
#Before
public void init() {
MockitoAnnotations.initMocks(this);
JsonParser parser = new JsonParser();
JsonElement jsonElement = parser.parse(json);
configurationService.loadConfiguration(jsonElement, "id");
AppContext.getContext().applyConfiguration(configurationService);
connectionProvider = ConnectionProvider.newInstance();
}
You can ignore everything that isn't the first and last line of it. I make a new ConnectionProvider object, so I would think that one test shoudldn't affect another, because they're operating on two separate objects.
This is more straightforward than you think: The test works when you comment out those lines because socketEventObserved is not getting called when it's the second test of the run. This is probably a problem with code that you haven't posted above.
Since it seems that the culprit may be buried in an impractical volume of code, here are a few debugging tips and general sources of test pollution:
First and foremost, set a breakpoint everywhere that socketEventObserved is called, and compare between single-test runs and multi-test runs. If you see the same behavior Mockito sees, then it's not Mockito.
As it turned out to be in this case, keep an eye out for actions that may occur on other threads (particularly to listeners). Using a Mockito timeout can help there:
verify(mockedObserver, timeout(2000))
.socketEventObserved(socketEventCaptor.capture());
You seem to be working with I/O channels, which sometimes involve buffering or flushing policies that can be triggered only when a certain number of tests are run, or if tests are run in certain order. Make sure that your #Before method fully resets state, including any modes or buffers that your code may touch.
You interact with AppContext.getInstance() and ConnectionProvider.newInstance(), both of which are static method calls. I'm less worried about the latter, unless it conserves instances in spite of its name, but the former may not take kindly to multiple initializations. In general, in your system-under-test, keep an eye out for writes to global state.
Mockito itself keeps static state. Mockito keeps its internal state static and thread-scoped (through ThreadLocal), and at times a test can leave Mockito in an invalid internal state that it cannot detect (because an operation is half-completed, for instance). Add an #After method to detect this case:
#After public void checkMockito() { Mockito.validateMockitoUsage(); }
...or switch to using MockitoRule or MockitoJUnitRunner, which do this and initMocks(this) automatically.
Finally, Mockito isn't perfect: It uses proxy objects to override methods, which also means it will silently fail to mock final methods and some non-public methods that work with nested classes (as those require the compiler to generate synthetic methods you can't see). If your mockedObserver has any final or limited-visibility methods, it may cause real code and mocked code to interact in a way that makes the system's behavior hard-to-predict.
I've been reading up on (and experimenting with) several Java mocking APIs such as Mockito, EasyMock, JMock and PowerMock. I like each of them for different reasons, but have ultimately decided on Mockito. Please note though, that this is not a question about which framework to use - the question really applies to any mocking framework, although the solution will look different as the APIs are (obviously) different.
Like many things, you read the tutorials, you follow the examples, and you tinker around with a few code samples in a sandbox project. But then, when it comes time to actually use the thing, you start to choke - and that's where I am.
I really, really like the idea of mocking. And yes, I am aware of the complaints about mocking leading to "brittle" tests that are too heavily coupled with the classes under test. But until I come to such a realization myself, I really want to give mocking a chance to see if it can add some good value to my unit tests.
I'm now trying to actively use mocks in my unit tests. Mockito allows both stubbing and mocking. Let's say we have a Car object that has a getMaxSpeed() method. In Mockito, we could stub it like so:
Car mockCar = mock(Car.class);
when(mockCar.getMaxSpeed()).thenReturn(100.0);
This "stubs" the Car object to always return 100.0 as the max speed of our car.
My problem is that, after writing a handful of unit tests already...all I'm doing is stubbing my collaborators! I'm not using a single mock method (verify, etc.) available to me!
I realize that I'm stuck in a "stubbing state of mind" and I'm finding it impossible to break. All this reading, and all this excitement building up to using mocks in my unit testing and... I can't think of a single use case for behavior verification.
So I backed up and re-read Fowler's article and other BDD-style literatures, and still I'm just "not getting" the value of behavior verification for test double collaborators.
I know that I'm missing something, I'm just not sure of what. Could someone give me a concrete example (or even a set of examples!) using, say, this Car class, and demonstrate when a behavior-verifying unit test is favorable to a state-verifying test?
Thanks in advance for any nudges in the right direction!
Well, if the object under test calls a collaborator with a computed value, and the test is supposed to test that the computation is correct, then verifying the mock colaborator is the right thing to do. Example:
private ResultDisplayer resultDisplayer;
public void add(int a, int b) {
int sum = a + b; // trivial example, but the computation might be more complex
displayer.display(sum);
}
Clearly, in this case, you'll have to mock the displayer, and verify that its display method has been called, with the value 5 if 2 and 3 are the arguments of the add method.
If all you do with your collaborators is call getters without arguments, or with arguments which are direct inputs of the tested method, then stubbing is probably sufficient, unless the code might get a value from two different collaborators and you want to verify that the appropriate collaborator has been called.
Example:
private Computer noTaxComputer;
private Computer taxComputer;
public BigDecimal computePrice(Client c, ShoppingCart cart) {
if (client.isSubjectToTaxes()) {
return taxComputer.compute(cart);
}
else {
return noTaxComputer.compute(cart);
}
}
I like #JB Nizet's answer, but here's another example. Suppose you want to persist a Car to a database using Hibernate after making some changes. So you have a class like this:
public class CarController {
private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
public void accelerate(Car car, double mph) {
car.setCurrentSpeed(car.getCurrentSpeed() + mph);
hibernateTemplate.update(car);
}
}
To test the accelerate method, you could just use a stub, but you wouldn't have a compete test.
public class CarControllerTest {
#Mock
private HibernateTemplate mockHibernateTemplate;
#InjectMocks
private CarController controllerUT;
#Test
public void testAccelerate() {
Car car = new Car();
car.setCurrentSpeed(10.0);
controllerUT.accelerate(car, 2.5);
assertThat(car.getCurrentSpeed(), is(12.5));
}
}
This test passes and does check the computation, but we don't know if the car's new speed was saved or not. To do that, we need to add:
verify(hibernateTemplate).update(car);
Now, suppose that if you try to accelerate past max speed, you expect the acceleration and the update not to happen. In that case, you would want:
#Test
public void testAcceleratePastMaxSpeed() {
Car car = new Car();
car.setMaxSpeed(20.0);
car.setCurrentSpeed(10.0);
controllerUT.accelerate(car, 12.5);
assertThat(car.getCurrentSpeed(), is(10.0));
verify(mockHibernateTemplate, never()).update(car);
}
This test will not pass with our current implementation of CarController, but it shouldn't. It shows you need to do more work to support this case and that one of the requirements is that you don't try to write to the database in this case.
Basically, verify should be used for exactly what it sounds like - to verify that something happened (or didn't happen). If the fact that it happened or didn't isn't really what you are trying to test, then skip it. Take the second example I made. One could argue that since the value wasn't changed, it doesn't really matter whether update was called or not. In that case, you can skip the verify step in the second example since the implementation of accelerate would be correct either way.
I hope it doesn't sound like I'm making a case for using verify a lot. It can make your tests very brittle. But it can also 'verify' that important things that were supposed to happen did happen.
My take on this is that every test case should contain EITHER
stubbing, plus one or more asserts OR
one or more verifys .
but not both.
It seems to me that in most test classes, you end up with a mixture of "stub and assert" test cases and "verify" test cases. Whether a test case does a "stub and assert" or does a "verify" depends on whether the value returned by a collaborator is important to the test. I need two examples to illustrate this.
Suppose I have an Investment class, which has a value in dollars. Its constructor sets the initial value. It has an addGold method, which increases the value of an Investment by the amount of gold times the price of gold in dollars per ounce. I have a collaborator called PriceCalculator that calculates the price of gold. I might write a test like this.
public void addGoldIncreasesInvestmentValueByPriceTimesAmount(){
PriceCalculator mockCalculator = mock( PriceCalculator.class );
when( mockCalculator.getGoldPrice()).thenReturn( new BigDecimal( 400 ));
Investment toTest = new Investment( new BigDecimal( 10000 ));
toTest.addGold( 5 );
assertEquals( new BigDecimal( 12000 ), toTest.getValue());
}
In this case, the result from the collaborator method is important to the test. We stub it, because we're not testing the PriceCalculator at this point. There's no need to verify, because if the method hadn't been called, the final value of the investment value would not be correct. So all we need is the assert.
Now, suppose there's a requirement that the Investment class notifies the IRS whenever anyone withdraws more than $100000 from an Investment. It uses a collaborator called IrsNotifier to do this. So a test for this might look like this.
public void largeWithdrawalNotifiesIRS(){
IrsNotifier mockNotifier = mock( IrsNotifier.class );
Investment toTest = new Investment( new BigDecimal( 200000 ));
toTest.setIrsNotifier( mockNotifier );
toTest.withdraw( 150000 );
verify( mockNotifier ).notifyIRS();
}
In this case, the test doesn't care about the return value from the collaborator method notifyIRS(). Or maybe it's void. What matters is just that the method got called. For a test like this, you'll use a verify. There may be stubbing in a test like this (to set up other collaborators, or return values from different methods), but it's unlikely that you'll ever want to stub the same method that you verify.
If you find yourself using both stubbing and verification on the same collaborator method, you should probably ask yourself why. What is the test really trying to prove? Does the return value matter to the test? Because this is usually a testing code smell.
Hope these examples are helpful to you.