How to verify static void method has been called with power mockito - java

I am using the following.
Powermock-mockito 1.5.12
Mockito 1.95
junit 4.11
Here is my utils class
public void InternalUtils {
public static void sendEmail(String from, String[] to, String msg, String body) {
}
}
here is gist of the class under test:
public class InternalService {
public void processOrder(Order order) {
if (order.isSuccessful()) {
InternalUtils.sendEmail(...);
}
}
}
And here is the test:
#PrepareForTest({InternalUtils.class})
#RunWith(PowerMockRunner.class)
public class InternalService {
public void verifyEmailSend() {
mockStatic(Internalutils.class);
doNothing().when(InternalUtils, "sendEmail", anyString(), any(String.class), anyString(), anyString());
Order order = mock(Order.class);
when(order.isSuccessful()).thenReturn(true);
InternalService is = new InternalService();
verifyStatic(times(1));
is.processOrder(order);
}
}
The above test fails. The verification mode given is none, but according to the code, if order is successful than email must be send.

If you are mocking the behavior (with something like doNothing()) there should really be no need to call to verify*(). That said, here's my stab at re-writing your test method:
#PrepareForTest({InternalUtils.class})
#RunWith(PowerMockRunner.class)
public class InternalServiceTest { //Note the renaming of the test class.
public void testProcessOrder() {
//Variables
InternalService is = new InternalService();
Order order = mock(Order.class);
//Mock Behavior
when(order.isSuccessful()).thenReturn(true);
mockStatic(Internalutils.class);
doNothing().when(InternalUtils.class); //This is the preferred way
//to mock static void methods.
InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
//Execute
is.processOrder(order);
//Verify
verifyStatic(InternalUtils.class); //Similar to how you mock static methods
//this is how you verify them.
InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
}
}
I grouped into four sections to better highlight what is going on:
1. Variables
I choose to declare any instance variables / method arguments / mock collaborators here. If it is something used in multiple tests, consider making it an instance variable of the test class.
2. Mock Behavior
This is where you define the behavior of all of your mocks. You're setting up return values and expectations here, prior to executing the code under test. Generally speaking, if you set the mock behavior here you wouldn't need to verify the behavior later.
3. Execute
Nothing fancy here; this just kicks off the code being tested. I like to give it its own section to call attention to it.
4. Verify
This is when you call any method starting with verify or assert. After the test is over, you check that the things you wanted to have happen actually did happen. That is the biggest mistake I see with your test method; you attempted to verify the method call before it was ever given a chance to run. Second to that is you never specified which static method you wanted to verify.
Additional Notes
This is mostly personal preference on my part. There is a certain order you need to do things in but within each grouping there is a little wiggle room. This helps me quickly separate out what is happening where.
I also highly recommend going through the examples at the following sites as they are very robust and can help with the majority of the cases you'll need:
https://github.com/powermock/powermock/wiki/Mockito (PowerMock Overview / Examples)
http://site.mockito.org/mockito/docs/current/org/mockito/Mockito.html (Mockito Overview / Examples)

Thou the above answer is widely accepted and well documented, I found some of the reason to post my answer here :-
doNothing().when(InternalUtils.class); //This is the preferred way
//to mock static void methods.
InternalUtils.sendEmail(anyString(), anyString(), anyString(), anyString());
Here, I dont understand why we are calling InternalUtils.sendEmail ourself.
I will explain in my code why we don't need to do that.
mockStatic(Internalutils.class);
So, we have mocked the class which is fine.
Now, lets have a look how we need to verify the sendEmail(/..../) method.
#PrepareForTest({InternalService.InternalUtils.class})
#RunWith(PowerMockRunner.class)
public class InternalServiceTest {
#Mock
private InternalService.Order order;
private InternalService internalService;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
internalService = new InternalService();
}
#Test
public void processOrder() throws Exception {
Mockito.when(order.isSuccessful()).thenReturn(true);
PowerMockito.mockStatic(InternalService.InternalUtils.class);
internalService.processOrder(order);
PowerMockito.verifyStatic(times(1));
InternalService.InternalUtils.sendEmail(anyString(), any(String[].class), anyString(), anyString());
}
}
These two lines is where the magic is,
First line tells the PowerMockito framework that it needs to verify the class it statically mocked. But which method it need to verify ??
Second line tells which method it needs to verify.
PowerMockito.verifyStatic(times(1));
InternalService.InternalUtils.sendEmail(anyString(), any(String[].class), anyString(), anyString());
This is code of my class, sendEmail api twice.
public class InternalService {
public void processOrder(Order order) {
if (order.isSuccessful()) {
InternalUtils.sendEmail("", new String[1], "", "");
InternalUtils.sendEmail("", new String[1], "", "");
}
}
public static class InternalUtils{
public static void sendEmail(String from, String[] to, String msg, String body){
}
}
public class Order{
public boolean isSuccessful(){
return true;
}
}
}
As it is calling twice you just need to change the verify(times(2))... that's all.

Related

how to unit test method using "Spring Data JPA" Specifications

I was playing with org.springframework.data.jpa.domain.Specifications, it's just a basic search :
public Optional<List<Article>> rechercheArticle(String code, String libelle) {
List<Article> result = null;
if(StringUtils.isNotEmpty(code) && StringUtils.isNotEmpty(libelle)){
result = articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)).and(ArticleSpecifications.egaliteLibelle(libelle)));
}else{
if(StringUtils.isNotEmpty(code)){
result= articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)));
}else{
result = articleRepository.findAll(Specifications.where(ArticleSpecifications.egaliteLibelle(libelle)));
}
}
if(result.isEmpty()){
return Optional.empty();
}else{
return Optional.of(result);
}
}
And that's actually working fine but I'd like to write unit tests for this method and I can't figure out how to check specifications passed to my articleRepository.findAll()
At the moment my unit test looks like :
#Test
public void rechercheArticle_okTousCriteres() throws FacturationServiceException {
String code = "code";
String libelle = "libelle";
List<Article> articles = new ArrayList<>();
Article a1 = new Article();
articles.add(a1);
Mockito.when(articleRepository.findAll(Mockito.any(Specifications.class))).thenReturn(articles);
Optional<List<Article>> result = articleManager.rechercheArticle(code, libelle);
Assert.assertTrue(result.isPresent());
//ArgumentCaptor<Specifications> argument = ArgumentCaptor.forClass(Specifications.class);
Mockito.verify(articleRepository).findAll(Specifications.where(ArticleSpecifications.egaliteCode(code)).and(ArticleSpecifications.egaliteLibelle(libelle)));
//argument.getValue().toPredicate(root, query, builder);
}
Any idea?
I was having almost the same problems as you had, and I changed my class that contains Specifications to be an object instead of just one class with static methods. This way I can easily mock it, use dependency injection to pass it, and test which methods were called (without using PowerMockito to mock static methods).
If you wanna do like I did, I recommend you to test the correctness of specifications with integration tests, and for the rest, just if the right method was called.
For example:
public class CdrSpecs {
public Specification<Cdr> calledBetween(LocalDateTime start, LocalDateTime end) {
return (root, query, cb) -> cb.between(root.get(Cdr_.callDate), start, end);
}
}
Then you have an integration test for this method, which will test whether the method is right or not:
#RunWith(SpringRunner.class)
#DataJpaTest
#Sql("/cdr-test-data.sql")
public class CdrIntegrationTest {
#Autowired
private CdrRepository cdrRepository;
private CdrSpecs specs = new CdrSpecs();
#Test
public void findByPeriod() throws Exception {
LocalDateTime today = LocalDateTime.now();
LocalDateTime firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
LocalDateTime lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
List<Cdr> cdrList = cdrRepository.findAll(specs.calledBetween(firstDayOfMonth, lastDayOfMonth));
assertThat(cdrList).isNotEmpty().hasSize(2);
}
And now when you wanna unit test other components, you can test like this, for example:
#RunWith(JUnit4.class)
public class CdrSearchServiceTest {
#Mock
private CdrSpecs specs;
#Mock
private CdrRepository repo;
private CdrSearchService searchService;
#Before
public void setUp() throws Exception {
initMocks(this);
searchService = new CdrSearchService(repo, specs);
}
#Test
public void testSearch() throws Exception {
// some code here that interact with searchService
verify(specs).calledBetween(any(LocalDateTime.class), any(LocalDateTime.class));
// and you can verify any other method of specs that should have been called
}
And of course, inside the Service you can still use the where and and static methods of Specifications class.
I hope this can help you.
If you are writing Unit Tests then you should probably mock the call to findAll() method of articleRepository Class using a mocking framework like Mockito or PowerMock.
There is a method verify() using which you can check if the mock is invoked for the particular parameters.
For Example, if you are mocking the findAll() method of articleRepository Class and want to know if this method is called with particular arguments then you can do something like:
Mokito.verify(mymock, Mockito.times(1)).findAll(/* Provide Arguments */);
This will fail the test if mock has not been called for the arguments that you provided.
Your problem is that you are doing too many things within that one method. You should have three different methods that work on articleRepository.
Then you can use mocking as the others suggest:
setup your mocks so that you know which call on articleRepository should be made
verify that exactly the expected calls are happening
Please note: these three methods should be internal; the main point there is: you can't test this method with ONE call from the outside; as it is doing more than one thing, depending on the input that you provide. Thus you need to create at least one test method for each of the potential paths in your code. And that becomes easier (from a conceptual point of view) when you separate your code into different methods.

Mockito NotaMockException

I am facing an issue with Mockito junit testing. I am new to it and am a bit confused with the problem I am facing. Any help on this would be appreciated.
class Activity{
public void firstMethod(){
String str = secondMethod();
}
public String secondMethod(){
String str = null;
/* some Code */
return str;
}
}
Getting exception :
*org.mockito.exceptions.misusing.NotAMockException:
Argument passed to when() is not a mock!*
in the below code
class ActivityTest(){
Activity act;
#Before
public void setup(){
act = new Activity();
}
#Test
public void testFirstMethod(){
Mockito.doReturn(Mockito.anyString()).when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
I am aware that activity is not a mock but I am not sure for a way around this as secondMethod() is a method in the same class. I need to write rule for secondMethod() as I have already done its Unit Testing. The definition of secondMethod() consists has external dependencies. Should I be mocking the external dependencies present in secondMethod() and writing rules for them rather than rule for secondMethod()?
I found this post:
Mockito Spy'ing on the object being unit tested
However separating the secondMethod() into a different class does not make sense. My method is related to this class. Creating a different class for testing does not seem right to me. Even mocking the actual class using spy() is not the most correct way as already explained in the post.
I don't think I should be creating a mock of the Activity class as that is the class I am testing. I would really appreciate help and insights into this.
As you noted, act is not a mock, and therefore you cannot record behavior on it. You could use Mockito.spy to, well, spy (or partially mock) the act object so that you only record the behavior of secondMethod and execute the actual code for firstMethod.
Note, however, that matchers can't be used in doReturn calls regardles of how you're mocking or spying your object. A return value must be a concrete object.
class ActivityTest() {
Activity act;
#Before
public void setup(){
act = Mockito.spy(new Activity()); // Here!
}
#Test
public void testFirstMethod(){
Mockito.doReturn("someString").when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
A slightly more elegant syntax allows you to use annotations instead of explicitly calling Mockito.spy, but it's a matter of taste really:
#RunWith(MockitoJUnitRunner.class)
class ActivityTest() {
#Spy
Activity act = new Activity();
#Test
public void testFirstMethod(){
Mockito.doReturn("someString").when(act).secondMethod();
act.firstMethod();
verify(act).secondMethod();
}
}
There is no reason to mock anything in this example. Since there are no dependencies and both methods are public, you can test them directly.
public class ActivityTest() {
private Activity act = new Activity();
#Test
public void testSecondMethod(){
assertEquals("expected-value", act.secondMethod());
}
#Test
public void testFirstMethod() {
act.firstMethod();
// success if no exception occurs
}
}
Since firstMethod does not have any detectable effect on the Act instance, nor on any dependency (since there are none) you can simply call the method and be satisfied if no exception is thrown. One could also reason that such a method should not be tested at all.
I assume the example given is a simplification of a class where calling firstMethod actually does have side effects, who knows...
Here are some hints:
Mock the Activity.
Tweak the behavior of secondMethod with when / then / doReturn
Use doCallRealMethod when firstMethod is invoked.
Hope it helps.

Unit Testing Java Code - Mocking a non-static method of a different class

public class First {
public First(){
}
public String doSecond(){
Second second = new Second();
return second.doJob();
}
}
class Second {
public String doJob(){
return "Do Something";
}
}
Here I want to test the method "doSecond()" of class "First". For the same, I want to mock the method "doJob" of class "Second".
I know that I can create a mocked instance of class "Second" using the code below.
Second sec = mock(Second.class);
when(sec.doJob()).thenReturn("Stubbed Second");
But I cannot relate this mocked instance with class "First" as of the current code.
Without refactoring the source code, is there any way by which i can achieve the requirement.
Please help.
Take a look at powermock's ability to intercept calls to new and return mocks instead
https://code.google.com/p/powermock/wiki/MockConstructor
This doesn't require changing any sourcecode.
here's the test code where we actually return a mock when First.doSecond() calls new Second()
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class TestFirst {
#Test
public void mockSecond() throws Exception{
Second mock = PowerMockito.mock(Second.class);
PowerMockito.whenNew(Second.class).withNoArguments().thenReturn(mock);
PowerMockito.when(mock.doSecond()).thenReturn("from mock");
First first = new First();
assertEquals("from mock", first.doSecond());
}
}
It's tricky to mock an instance that you create inside of a method, but it's possible.
Using PowerMock, you can accomplish this with the PowerMock.expectNew() method:
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class StackOverflowTest {
#Test
public void testFirst() throws Exception {
Second secondMock = EasyMock.createMock(Second.class);
PowerMock.expectNew(Second.class).andReturn(secondMock);
expect(secondMock.doSecond()).andReturn("Mocked!!!");
PowerMock.replay(secondMock, Second.class);
String actual = new First().doSecond();
PowerMock.verify(secondMock, Second.class);
assertThat(actual, equalTo("Mocked!!!"));
}
}
Effectively, PowerMock is proxying the creation of the new object and substituting whatever value we want when we invoke doSecond().
So, it's possible. However, this is a terrible practice to get into.
One typically wants to mock objects if they involve an outside concern, such as another layer (i.e. database, validation), or if the desired output is coming from other objects that are injected but are safe enough to consider tested.
If your method is capable of getting or retrieving data from a non-injectable source, you should not want to mock that out.
Considering that your method is simple and straightforward, you should really not need to do any mocks here at all. But if you felt that you were forced to, you could do one of a few things:
Create a factory for the creation of Second, and mock the results of the returning factory object with Mockito.
Pass in an instance of Second to that method, and use Mockito as the mock instance.
Declare it as a field (i.e. injected dependency), and use Mockito.
For completeness, here is how the test can be written with the JMockit mocking API, without any refactoring of the original code under test:
public class ExampleTest
{
#Test
public void firstShouldCallSecond(#Mocked final Second secondMock) {
new NonStrictExpectations() {{
secondMock.doJob(); result = "Mocked!!!";
}};
String actual = new First().doSecond();
assertEquals("Mocked!!!", actual);
}
}

Easymock - nested void method testing (spying)

How to spy parameter 'param' in nested method during getData() mock testing ?
Is it possible with Easymock 3 ?
Source code
public class ServiceLogic {
public void getData(){
// some business logic
serviceDAO.executeStatement(param);
}
}
Easymock test :
ServiceLogic _serviceLogicMock = EasyMock.createNiceMock(ServiceLogic.class);
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);
_serviceLogicMock.setServiceDAO(_serviceDAOMock);
//some other method calls -> .execute(...).andReturn(...);
EasyMock.replay(_serviceLogicMock);
//run
_serviceLogicMock.getData();
How to check with EasyMock whether executeStatement() method is called with correct parameter ?!
Your test does seem wrong:
Your unit test is about testing ServiceLogic why do you mock it then ?
Also you don't have any expectations on any interaction with your ServiceDAO mock.
As the question is tagged Mockito, I propose the following solution (minus the imports) that you can adapt to your code :
#RunWith(MockitoJUnitRunner.class)
public class ServiceLogicTest {
#Mock ServiceDAO serviceDAO;
#InjectMocks ServiceLogic serviceLogic;
#Test
public void ensure_executeStatement_is_called_with_right_param() throws Exception {
// given
String input = "Some input";
// when
serviceLogic.getDataFrom(input);
// then
verify(serviceDAO).executeStatement("expected param");
}
}
When writing tests, I like to use the BDD (Behavior Driven Development) style to guide me to what I want to test. I encourage you to practice it, you can have look at the wiki page.
So for your question, you should take a look at the verify line, it put the mock in a verification mode, so can actually verify that the method executeStatement is actually called with the argument value "expected param".
If you have more complex parameters, you can use some matchers using the Hamcrest library:
verify(serviceDAO).executeStatement(argThat(hasProperty("propertyName")));
Or you can use a Mockito's ArgumentCaptor in combination with the FEST-Assert library (usually my preferred approach):
ArgumentCaptor<ComplexArgument> argCaptor = ArgumentCaptor.forClass(ComplexArgument.class);
verify(serviceDAO).executeStatement(argCaptor.capture());
assertThat(argCaptor.getValue()).isNotNull().satisfies(myComplexArgumentCondition());
The main idea is to have understandable code, in production code and in test code.
For further reading have a look at the Mockito Javadoc.
Like #Brice, I prefer Mockito to EasyMock, but here's the EasyMock version that is closer to your original example since your example was EasyMock.
public class ServiceLogicTest {
#Test
public void ensure_executeStatement_is_called_with_right_param() throws Exception {
ServiceLogic _serviceLogicUT = new ServiceLogic();
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);
_serviceLogicUT.setServiceDAO(_serviceDAOMock);
String input = "Some input";
//some other method calls -> .execute(...).andReturn(...);
_serviceDaoMock.executeStatement("expected para"); // assuming a void method
EasyMock.replay(_serviceDaoMock);
// run
_serviceLogicUT.getDataFrom(input);
// verifies that the expected calls were made
EasyMock.verify(_serviceDaoMock);
}
}
EasyMock also has argument capture functionality. That would look like this:
public class ServiceLogicTest {
#Test
public void ensure_executeStatement_is_called_with_right_param() throws Exception {
ServiceLogic _serviceLogicUT = new ServiceLogic();
ServiceDAO _serviceDAOMock = EasyMock.createNiceMock(ServiceDAO .class);
_serviceLogicUT.setServiceDAO(_serviceDAOMock);
String input = "Some input";
//some other method calls -> .execute(...).andReturn(...);
Capture<ComplexParam> capturedParam = new Capture<ComplexParam>();
_serviceDaoMock.executeStatement(EasyMock.capture(capturedParam)); // assuming a void method
EasyMock.replay(_serviceDaoMock);
// run
_serviceLogicUT.getDataFrom(input);
ComplexParam actualParam = capturedParam.getValue();
// make various assertions on actual param
}
}
I think you can see from the two examples why many people prefer Mockito, but if there's some reason you prefer or are mandated to use EasyMock, you can do just about anything you can do with Mockito, just with more lines of code.
This should be possible with jmockit, unless you DAO has final methods. However, this is better and easier done with jMockit:
#Test
public void testMethod(#Mocked final ServiceDAO serviceDAO) {
new Expectations() {{
serviceDAO.executeStatement(expectedOParams);returns(expectedReturnValue)
}};
(new ServiceLogic(serviceDAO)).getData();
}
That's almost complete test save assertions. And it works with final, static, abstract and whatever methods.

jUnit - How to assert that inherited methods are invoked?

Let's say you have some 3rd-party library class that you want to extend, simply to add convenience methods to it (so you can call an inherited method with default parameters for example).
Using jUnit/jMock, is it possible to write an assertion / mock expection that tests that the correct inherited method is called?
For example, something like this:
class SomeClass extends SomeLibraryClass {
public String method(String code) {
return method(code, null, Locale.default());
}
}
How can I assert that method is being called?
You can make a further subclass inside your unit test that actually tells you:
public class MyTest {
boolean methodCalled = false;
#Test
public void testMySubclass(){
TestSomeClass testSomeClass = new TestSomeClass();
// Invoke method on testSomeclass ...
assertTrue( methodCalled);
}
class TestSomeClass extends SomeClass{
public String method(String code){
methodCalled = true;
}
}
}
Unit testing is more useful to verify the functionality of given methods, not to assert coverage. Unit tests that care more about what method got called know way more about the classes they are testing than they probably should, not to mention will be confusing to the reader.
Coverage tools like Cobertura or EMMA will tell you whether you properly covered your code.
It may indeed be better to only write integration tests in this case, but if you really want a unit test, you can have it just as easily as in any other case:
public class SomeClassTest
{
#Test
public void testMethod()
{
final String code = "test";
new Expectations()
{
SomeLibraryClass mock;
{
mock.method(code, null, (Locale) any);
}
};
new SomeClass().method(code);
}
}
This test uses the JMockit mocking API.
it's hard to tell without a more concrete example, but I'd guess that this ought to be an integration test--test the whole package together--rather than a unit test. Sometimes one can be too fine-grained with unit testing.

Categories

Resources