I am trying to mock a DAO layer Interface which looks something like this ...
public interface DummyDAO{
public List<VO> getSearchCriteria(String Id, Integer version) throws Exception;
}
In the implementation part, I run a query, and it fetches me a list of Value objects based on that query. How do I mock a List of VO's coming from a database. Is there a simple way to do this ?. I am trying to encourage my team to use Jmockit but I am still a newbie to this mocking tool. If you need more info please let me know.
Thanks
The answer here can depend partly on how the CUT (code under test) is using the List<VO>. For example, if your code is a RESTful service merely acting as a proxy and returning this List<VO> to the user, without examining the contents or anything, then this would suffice:
#Tested CUT cut;
#Injectable DummyDAO dao;
#Injectable List<VO> res;
#Test
public void testSomething() throws Exception {
new Expectations() {{
dao.getSearchCriteria(anyString, anyInt); result = res;
}};
List<VO> output = cut.methodBeingTested();
// assertions go here, like that output and res are the same
// you can also put Verifications here
}
If you are expecting to do analysis of the VOs then things can get more complex, like for example:
#Tested CUT cut;
#Injectable DummyDAO dao;
#Mocked VO vo;
#Test
public void testSomething() throws Exception {
final List<VO> res = new ArrayList<VO>();
Collections.addAll(res, vo, vo, vo, vo);
new Expectations() {{
dao.getSearchCriteria(anyString, anyInt); result = res;
}};
new Expectations(4) {{
vo.getFoo(); returns(5, 47, 13, -7);
}};
cut.methodBeingTested();
// assertions go here, like that you handled the negative number properly
// you can also put Verifications here
}
Notice here I did not mock the List -- if you are doing more complex operations it's better to stick with a real List and not have to mock all of its operations. I mock a single VO and add it to the list multiple times--this is OK because each time you examine it it will act differently and thus seem to be a different VO.
The examination, because it is happening 4 times, I moved to a different Expectations block since you are expecting it to happen 4 times. I'm just doing this to show off the expectations block since in this case it could be just as easily accomplished by having vo.getFoobar(); times=4; returns(5, 47, 13, -7); in the original block... alternatively, this second block could look like
new StrictExpectations(4) {{
vo.getFoo(); returns(5, 47, 13, -7);
vo.getBar(); returns("foo", "bar", "baz", "quux");
}};
In this case, the times field would not work and you'd have to have it in a separate block - this block is saying it expects to have getFoo() and getBar() called, alternating, exactly 4 times--as you would want to do if iterating through a list and looking at both properties each time.
I hope I have given you food for thought; without knowing more of your specific use case I can't be more specific myself.
One simple way to do that is using Mockito.spy() .The spy method create a proxy of your instance that give to you the opportunity to simulate the behavior of one method.
You could create one list that will be returned when you call your dao method.
Example:
yourDao = spy(new YourDaoImplementation())
doReturn(yourExampleList).when(yourDao).getSearchCriteria(any(String.class), any(Integer.class));
If you really want to test your dao, you could use a light weight data base as HSQLDB
Related
I have the following method and I wrote a unit test in Java for this method. It is coveraged except from the if statement and I also need to test this part.
#InjectMocks
private ProductServiceImpl productService;
public void demoMethod(final List<UUID> productUuidList) {
if (productUuidList.isEmpty()) {
return;
}
final Map<ProductRequest, PriceOverride> requestMap = getPriceRequests(uuidList);
productService.updateByPriceList(priceRequestMap, companyUuid);
}
However, as the method execution is finalized and does not return anything when uuidList is empty, I cannot test this if block.
So:
How can I test this if block?
Should I create a new Unit Test method for testing this if block? Or should I add related assert lines to the current test method?
Update: Here is my test method:
#Test
public void testDemoMethod() {
final UUID uuid = UUID.randomUUID();
final List<Price> priceList = new ArrayList<>();
final Price price = new Price();
price.setUuid(uuid);
priceList.add(price);
productService.demoMethod(Collections.singletonList(uuid));
}
The general idea is that you don't want to test specific code, but you want to test some behaviour.
So in your case you want to verify that getPriceRequests and priceService.updateByPriceList are not called when passing in an empty List.
How exactly you do that depends on what tools you have available. The easiest way is if you already mock priceService: then just instruct your mocking liberary/framework to verify that updateByPriceList is never called.
The point of doing a return in your if condition is that the rest of the code is not executed. I.e., if this // code omitted for brevity was to be executed, the method would not fill it's purpose. Therefore, just make sure that whatever that code does, it was not done if your list is empty.
You have 3 choices:
Write a unit test with mocks. Mockito allows you to verify() whether some method was invoked.
Write a more high-level test with database. When testing Service Facade Layer this is usually a wiser choice. In this case you can obtain the resulting state of DB in your test to check whether it did what it had to.
Refactor your code to work differently
Check out Test Pyramid and How anemic architecture spoils your tests for more details.
I want to mock a query provided on my repository like this:
#Test
public void GetByEmailSuccessful() {
// setup mocks
Mockito.when(this.personRepo.findAll()
.stream()
.filter(p -> (p.getEmail().equals(Mockito.any(String.class))))
.findFirst()
.get())
.thenReturn(this.personOut);
Mockito.when(this.communityUserRepo.findOne(this.communityUserId))
.thenReturn(this.communityUserOut);
...
My #Before method looks like this:
#Before
public void initializeMocks() throws Exception {
// prepare test data.
this.PrepareTestData();
// init mocked repos.
this.personRepo = Mockito.mock(IPersonRepository.class);
this.communityUserRepo = Mockito.mock(ICommunityUserRepository.class);
this.userProfileRepo = Mockito.mock(IUserProfileRepository.class);
}
Sadly when I run the test I receive the error:
java.util.NoSuchElementException: No value present
When I double-click the error it points at the .get() method of the first lambda.
Have any of you successfully mocked a lambda expression and know how I can solve my problem?
There's no need to mock such deep calls. Simply mock personRepo.findAll() and let the Streaming API work as normal:
Person person1 = ...
Person person2 = ...
Person person3 = ...
List<Person> people = Arrays.asList(person1, person2, ...);
when(personRepo.findAll()).thenReturn(people);
And then instead of
.filter( p -> (p.getEmail().equals(Mockito.any(String.class))) )
just set/mock email on your Person objects to be the expected value.
Alternatively, consider implementing PersonRepo.findByEmail.
Two things:
Mockito.when(this.personRepo.findAll()
.stream()
.filter(p -> (p.getEmail().equals(Mockito.any(String.class))))
.findFirst()
.get())
.thenReturn(this.personOut);
First, you're trying to mock a chain of five different method calls. Mockito doesn't handle this very well; though the RETURNS_DEEP_STUBS answer (if put on personRepo) would save and return stub objects where applicable, each call to when will itself stub exactly one call.
Second, Mockito matchers aren't flexible enough to work deeply in calls; calls to when should contain exactly one method call without chaining, and calls to Mockito matchers like any should stand in for exactly one of the arguments in that method. The way you have it, you're creating a predicate p -> (p.getEmail().equals(null)) and leaving a matcher on the stack to break things later.
Use Alex Wittig's answer to solve this problem, and be mindful of stubbing and using matchers correctly in future problems.
I am admittedly new to JMockit, but I am for some reason having trouble mocking System.getProperties(). Thanks to the help of following post:
https://stackoverflow.com/questions/25664270/how-can-i-partially-mock-the-system-class-with-jmockit-1-8?lq=1
I can successfully mock System.getProperty() using JMockit 1.12:
#Test
public void testAddSystemProperty_String() {
final String propertyName = "foo";
final String propertyValue = "bar";
new Expectations(System.class) {{
System.getProperty(propertyName);
returns(propertyValue);
}};
assertEquals(propertyValue, System.getProperty(propertyName));
}
But the eerily similar code for mocking getProperties() barfs:
#Test
public void testAddSystemProperty_String() {
final String propertyName = "foo";
final String propertyValue = "bar";
final Properties properties = new Properties();
properties.setProperty(propertyName, propertyValue);
new Expectations(System.class) {{
System.getProperties();
returns(properties);
}};
assertEquals(1, System.getProperties().size());
}
I get the following exception that points to the "returns" method:
Missing invocation to mocked type at this point;
please make sure such invocations appear only after
the declaration of a suitable mock field or parameter
Also, how do I mock both methods at the same time? If I put them in the same Expectations block (with the getProperty() first), then I do not see the exception, but System.getProperties() returns the real system properties, not the mocked ones; though getProperty(propertyName) returns the mocked value. I find that totally wonky behavior.
I see from this post that certain methods cannot be mocked, but System.getProperties() is not on that list:
JMockit NullPointerException on Exceptions block?
I am also finding that a lot of solutions on SO that worked with JMockit 2-3 years ago are totally non-compilable now, so apparently things change a lot.
System.getProperties() is indeed one of the methods excluded from mocking in JMockit 1.12. The exact set of such excluded methods can change in newer versions, as new problematic JRE methods are found.
There is no need to mock System.getProperty(...) or System.getProperties(), though. The System class provides setProperty and setProperties methods which can be used instead.
Hopefully someone else finds this useful:
This can be solved with Mockito / PowerMock (1.5.3).
Note that I am testing a utility that will exhaustively try to find the property value given a list of possible sources. A source could be a system property, an environment variable, a meta-inf services file, a jndi name, a thread local, a file on disk, an ldap, basically anything that can perform a lookup.
#RunWith(PowerMockRunner.class)
#PrepareForTest({ClassThatDirectlyCallsSystemInCaseItIsNestedLikeInMyCase.class})
public class ConfigPropertyBuilderTest {
#Test
public void testAddSystemProperty_String_using_PowerMockito() {
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty(propertyName)).thenReturn(propertyValue);
PowerMockito.when(System.getProperties()).thenReturn(new Properties() {{
setProperty(propertyName, propertyValue);
}});
// Here is realistic case of calling something that eventually calls System
// new configBuilder().addEnvironmentVariable(propertyName)
// .addSystemProperty(propertyName)
// .getValue();
// Here is simplified case:
assertEquals(1, System.getProperties().size());
assertEquals(propertyValue, System.getProperty(propertyName));
}
}
I could call System.setProperty(), but when you start getting into the other sources, it becomes less clear.
Note that I do not specifically care about the value returned by System.getProperty() either; I simply want to ensure that it is called if the first look up fails.
For example, in the above code snippet, the environment variable does not exist, so System.getProperty() should be called. If the environment variable existed (as it does in the next test case which is not shown), then I want to verify that System.getProperty() was not called because it should have short circuited.
Because of the difficulties in faking out the other sources using real files, real ldap, real APIs, etc, and because I want to verify certain APIs are either called or not called, and because I want to keep the tests looking consistent, I think mocking is the correct methodology (even though I may be trying to mock stuff that is not recommended in order to keep it all looking consistent). Please let me know if you think otherwise.
Also, while I do not understand the difficulties of maintaining these mocking frameworks (especially the cglib based ones), I understand the difficulties do exist and I can appreciate the sort of problems you face. My hat goes off to you all.
I have a simple POJO that contains a Map<String,Widget> property:
private Map<String, Widget> widgetCache = new HashMap<String, Widget>();
#Override
public Logger newWidget(String name, Widget widget) {
// First, print the contents of widgetCache in pretty print format.
Map<String, Widget> map = widgetCache;
List<String> keys = new ArrayList<String>(map.keySet());
System.out.println("Printing..." + keys.size());
for (String key: keys)
System.out.println(key + ": " + map.get(key).getName());
if(!widgetCache.containsKey(name)) {
System.err.println("I don't contain " + name);
widgetCache.put(name, widget);
}
return widgetCache.get(name);
}
Simple enough: it just doesn't allow duplicate Widgets from being inserted into the map. When I go to test this in a JUnit test method using Mockito (1.9.5):
CachingWidgetFactory fixture = new CachingWidgetFactory();
// By the way, I get errors if I try to make this next line:
// HashMap<String,Widget> mockMap = Mockito.mock(HashMap<String,Widget>.class);
// How do I enforce generics here when defining a mock?
HashMap mockMap = Mockito.mock(HashMap.class);
fixture.setLoggerCache(mockMap);
fixture.newWidget("Widget-A", new Widget("Widget-A"));
fixture.newWidget("Widget-A", new Widget("Widget-A"));
Mockito.verify(mockMap, Mockito.times(1))
.put(Mockito.anyString(), Mockito.<Logger>any());
I get the test failing with the following JUnit output:
org.mockito.exceptions.verification.TooManyActualInvocations:
hashMap.put(<any>, <any>);
Wanted 1 time:
And in the (STDOUT) console output, I see this:
Printing...0
I don't contain Widget-A
Printing...0
I don't contain Widget-A
So it looks like the mock that Mockito is returning is allowing the 2nd (duplicate) insert. However, when I remove the Mockito mockMap entirely, and make the test method look like:
CachingWidgetFactory fixture = new CachingWidgetFactory();
fixture.newWidget("Widget-A", new Widget("Widget-A"));
fixture.newWidget("Widget-A", new Widget("Widget-A"));
Then in the console output, I get:
Printing...0
I don't contain Widget-A
Printing...1
Now the (non-mocked) code is correctly preventing the duplicate insert. So it's almost as if Mockito is returning a new HashMap every time newWidget is being called. What's going on here, and why? (And bonus points if you can help me on the generic issue mentioned above.) Thanks in advance.
That's a common mistake. You have to remember that you mocked HashMap. So, mockito is not giving you a new map everytime, it just don't know how to behave because you mocked the HashMap.
Giving that, it will behave as you tell it to behave. If you haven't said anything, it will return default values/do nothing when you call your methods. So, at the line
if (!widgetCache.containsKey(name))
because you didnt say how it should behave, it will return the default value of false. You can mock the map to return false at the second call using Mockito with something like
given(hashMap.containsKey(name)).willReturn(false, true);
With that, HashMap will return that "contains" the key at the second call of containsKey with the given name. You can read its documentation here
Another thing you could do is to give to it a real implementation of HashMap, but I prefer the "mock" way :)
EDIT
I gave the link to BDDMockito, but it works the same way with when->thenReturn. It's just syntax sugar :) I find it easier to read.
// How do I enforce generics here when defining a mock?
HashMap mockMap = Mockito.mock(HashMap.class);
Handling generics is much easier if you use the mockito annotations, e.g.
#Mock
HashMap<String, Widget> mockMap;
and then in your setup method:
MockitoAnnotations.init(this);
But to your problem, just use
HashMap<String, Widget> map=new HashMap<String, Widget>();
so that the test uses a real HashMap that behaves like one, since that is the thing you want to test. If you're going to mock all the HashMap operations yourself, chances are you are making some kind of mistake (like forgetting to mock a method).
I have a JUnit class with different methods to perform different tests.
I use Mockito to create a spy on real instance, and then override some method which is not relevant to the actual test I perform.
Is there a way, just for the sake of cleaning up after me in case some other tests that run after my tests also use the same instances and might execute a mocked method they didn't ask to mock, to un-mock a method?
say I have a spy object called 'wareHouseSpy'
say I overriden the method isSomethingMissing :
doReturn(false).when(wareHouseSpy).isSomethingMissing()
What will be the right way to un-override, and bring things back to normal on the spy i.e make the next invokation of isSomethingMissing to run the real method?
something like
doReturn(Mockito.RETURN_REAL_METHOD).when(wareHouseSpy).isSomethingSpy()
or maybe
Mockito.unmock(wareHouseSpy)
Who knows? I couldn't find nothing in that area
Thanks!
Assaf
I think
Mockito.reset(wareHouseSpy)
would do it.
Let's say most of your tests use the stubbed response. Then you would have a setUp() method that looks like this:
#Before
public void setUp() {
wareHouseSpy = spy(realWarehouse);
doReturn(false).when(wareHouseSpy).isSomethingMissing();
}
Now let's say you want to undo the stubbed response and use the real implementation in one test:
#Test
public void isSomethingMissing_useRealImplementation() {
// Setup
when(wareHouseSpy.isSomethingMissing()).thenCallRealMethod();
// Test - Uses real implementation
boolean result = wareHouseSpy.isSomethingMissing();
}
It depends whether you are testing with TestNG or JUnit.
JUnit creates a new instance of itself for each test method. You basically don't have to worry about reseting mocks.
With TestNG, you have to reset the mock(s) with Mockito.reset(mockA, mockB, ...) in either an #BeforeMethod or an #AfterMethod
The "normal" way is to re-instantiate things in your "setUp" method. However, if you have a real object that is expensive to construct for some reason, you could do something like this:
public class MyTests {
private static MyBigWarehouse realWarehouse = new MyBigWarehouse();
private MyBigWarehouse warehouseSpy;
#Before
public void setUp() {
warehouseSpy = spy(realWarehouse); // same real object - brand new spy!
doReturn(false).when(wareHouseSpy).isSomethingMissing();
}
#Test
...
#Test
...
#Test
...
}
Maybe I am not following but when you have a real object real:
Object mySpy = spy(real);
Then to "unspy" mySpy... just use real.
As per the documentation, we have
reset(mock);
//at this point the mock forgot any interactions & stubbing
The documentation specifies further
Normally, you don't need to reset your mocks, just create new mocks
for each test method. Instead of #reset() please consider writing
simple, small and focused test methods over lengthy, over-specified
tests.
Here's an example from their github repo which tests this behavior and uses it:
#Test
public void shouldRemoveAllInteractions() throws Exception {
mock.simpleMethod(1);
reset(mock);
verifyZeroInteractions(mock);
}
reference : ResetTest.java
Addressing this piece specifically:
Is there a way, just for the sake of cleaning up after me in case some other tests that run after my tests also use the same instances and might execute a mocked method they didn't ask to mock, to un-mock a method?
If you are using JUnit, the cleanest way to do this is to use #Before and #After (other frameworks have equivalents) and recreate the instance and the spy so that no test depends on or is impacted by whatever you have done on any other test. Then you can do the test-specific configuration of the spy/mock inside of each test. If for some reason you don't want to recreate the object, you can recreate the spy. Either way, everyone starts with a fresh spy each time.