Mockito: Detect when a method on a private resource is invoked - java

I need to write a test for this class. I need to verify that when the size of the list is exactly 2 then the modelService.save is called. Is it also possible to get to the object productModel?
I don't know where to start.
public class SoldMaterialPrepareInterceptor implements PrepareInterceptor<SoldMaterialModel> {
#Resource
private ModelService modelService;
#Override
public void onPrepare(SoldMaterialModel soldMaterialModel, InterceptorContext interceptorContext) throws InterceptorException {
setSAPSubstance(soldMaterialModel);
}
private void setSAPSubstance(SoldMaterialModel soldMaterialModel) {
ProductModel productModel = soldMaterialModel.getBaseProduct();
Set superCatagoriesList = [....]// gets the list somehow
if (superCatagoriesList.size() == 2) {
productModel.setSupercategories(superCatagoriesList);
modelService.save(productModel);
}
}
}

It is not a problem that the modelService field is private, it is a class field for which private access modifier is usually expected. You need to check the invocation of its save() method, which in turn cannot be private, otherwise it would not be possible to call it from the interceptor class.
As for the test, assuming the superCatagoriesList (which is actually a Set and not a List and also should be generic) gets its content directly or indirectly (e.g. through productModel) from the soldMaterialModel parameter, your task is to write a test, which populates soldMaterialModel with such values so that superCatagoriesList.size() will be 2, and then you can verify that the modelService.save() method was called exactly once with e.g. something like
Mockito.verify(modelService).save(any(ProductModel.class));

I found that when it is difficult to test a method most often there is a design problem of the code I am testing. I suggest a minor to refactoring first: move setSAPSubstance to SoldMaterialModel class and make it public. That is where that method needs to be (see feature envy). Of course modelService.save(productModel); will stay in the interceptor and it will be called only if needed.
Then you will only have to test the two public methods

Is that the whole class? Then I think I see the issue. There are no non-private ways to set the ModelService. When the whole app runs, the dependency injection framework uses reflection to set the ModelService. When you run the test, you don't have anyway to inject a mock. You have a few options.
You can add a constructor to SoldMaterialPrepareInterceptor which takes the ModelService as a parameter. Then you can use that in your test. You would probably also have to add a no-argument constructor because that's how your dependency injection framework creates it. Better yet, you could figure out how to configure the framework to use the new constructor that takes the ModelService.
public class SoldMaterialPrepareInterceptor {
// Public constructor if needed for dependency injection
public SoldMaterialPrepareInterceptor () { }
// If just used for test use protected or package private
// If used with dependency injection, use public.
protected SoldMaterialPrepareInterceptor(ModelService modelService){
this.modelService = modelService
}
The test class is usually in the same package as the actual class, so package private or protected scope is enough. Then the test looks something like this (Assuming Mockito and Junit. Logically, Spock and other frameworks would be similar):
ModelService modelService = Mockito.mock(ModelService.class);
SoldMaterialPrepareInterceptor interceptor = new SoldMaterialPrepareInterceptor(modelService);
// setup SoldMaterialModel and InterceptorContext
interceptor.onPrepare(soldMaterialModel, interceptorContext);
Mockito.verify(modelService, Mockito.times(0)).save(soldMaterialModel);

Related

Java private vs default method protection

Java Question: I am working on a class (call it ProcessorA that only extends Object. It is also stateless). It will reside in a Spring Service on a Web Server. The class declares several public methods as the class' API.
I want to test this class with a simple JUnit test. I need to test some functionality that is a few method calls deep inside of 1 public method. However, between the API Method and the method to test there are several classes would be loaded at runtime by Spring in the Web Server.
I can completely by-pass this by declaring the method to be tested as a 'default' method and calling it directly from an instance (of ProcessorA) from the JUnit test.
I have been told that this is NOT a best practice.
However, I am at a loss as to exactly what is gained by further restricting access to the method to be tested.
So, what is it that can be gained by declaring a method as private over default (which is more restrictive than "protected" (which by inclusion is also verboten). \
public class ProcessorA {
public methodA(String input) throws ValidationException {
doSomeValidationStuff(input);
doStuffToTest(input);
}
private doSomeValidationStuff(String input) throws ValidationException {
//Libraries that are not loaded at execution and not available for the JUnit test
}
doStuffToTest(String input) {
//Code to be tested}
}
}
class MyJunitTest {
#Test
void doStuffToTestTest() {
ProcessorA processorA = new ProcessorA();
String testData = "test data String";
assertNotNull( processorA.doStuffToTest(testDate));
}
}
The answer that I am looking for isn't for how to get around this constraint, but what is gained by blindly following a blanket directive that has (seemingly) no payoff.
Default scope in Java is a package-private scope which means that all classes from the same package can use this method. If you restrict it to private, only methods from the same class can do it. This is what we gain. It is your decision, do you need to expose this method to other classes or it is enough to just keep it private but don't expose something only for testing purposes.

When you mock a class in mockito framework, do you stand up actual mock class manually?

I am fairly new to mockito framework. I've been reading upon multiple tutorials in regards to it. One of them I was following is this: https://www.tutorialspoint.com/mockito/mockito_first_application.htm
There is a statement creating a mock of Stock Service.
In this example, we've created a mock of Stock Service to get the dummy price of some stocks
My question is Stock Service is a real service class or mock service class you have to manually stand up for mimicking the real service class. I am a bit confused. Having basic understanding of junit framework. What I had practiced before was if there is a service class Foo then I used actual class that provides all the exposed methods.
public class Foo {
public Foo() { } // construtor
public String returnAddress(String userId) {
// ...
return dataAccesobj.getAddress(userId);
}
}
Calling foo.returnAddress(..) in unit test if I remember right.
The reason I am asking this question is while I was working with mockitoto create a test method for a class, I ran into a unique(?) challenge.
I started with a real service class which depends on its super class constructor to return its instance. The challenge I ran into was this super class constructor initiates DB connection and loading/parsing properties files which I do not need for my test. I was thinking about how to prevent DB connection and loading/reading prop files....
I thought I read from one of mockito tutorials you can isolate testing without having such services. I tried with #Mock and #Spy (not fully understanding well still what they are for..) but it didn't make a difference for output (maybe I misused those annotations).
So what I did was actually creating fake/mock class out of real service class (e.g. Foo) by simply copying it and renamed it as FooMock and put it in src/test/java folder in where unit test class is running from. I kept the mock class exactly same as the real service class except taking out unwanted logic such as db connection or loading/reading prop file for env specific. By doing that I was able to test one of exposed methods that read ldap directory...
I am sorry I got digressed but hope my point is clear at this point. I am not sure the way I handled this situation is right or wrong. I'd appreciate experienced engineers would clarify the way I handled the matter is acceptable in mockito way or not. If not, then plz advise me best way to handle it.
With Mockito,
a mock is an implementation of a wrapper class.
The mock object "wraps" the target of the mock
(the service in your example)
and allows you to define functionality of each method.
There are two mocked functionality options with Mockito;
call the wrapped method and don't call the wrapped method.
I don't know when it would make sense to call the wrapped method,
so I always use don't call the wrapped method.
After you create the mock,
use the Mockito.doReturn(returnvalue).when(mockObject).method(method parameters) method to mock functionality.
Edit: some more info.
I will assume that you are using junit v4.
The details of this will differ based on the the junit major release number,
but the actual work will be the same.
Use annotations to define your Mock objects (#Mock),
except in a few special cases.
This will create mocks of non-final classes,
abstract classes,
and interfaces.
Create a "before-test" method using the #Before annotation;
I traditionally name this method preTestSetup,
but the actual name does not matter.
Call MockitoAnnotations.initMocks(this) as the first line of code
in the "before-test" method.
This will find the #Mock annotations and instantiate a mock for each.
Use the ReflectionTestUtils.setField method to inject the mocks into your object (assuming that you don't have setter methods,
which I traditionally don't like).
Define the mocked functionality of each method using the Mockito.doReturn(returnvalue).when(mockObject).method(method parameters) technique.
Here is some example code
(caveat:
this should be fully functional,
but I did not compile it):
public interface MyService
{
String blammy(SomeParameter parameter);
}
public class UsesMyService
{
#Autowired
private MyService myService;
public String kapow(final SomeParameter parameter)
{
return myService.blammy(parameter);
}
}
public class UnitTestUsesMyService
{
private UsesMyService classToTest;
#Mock
private MyService mockMyService;
#Mock
private SomeParameter mockSomeParameter;
#Before
public void preTestSetup()
{
MockitoAnnotations.initMocks(this);
classToTest = new UsesMyService();
doReturn("Blam").when(mockMyService).blammy(mockSomeParameter);
ReflectionTestUtils.setField(
classToTest,
"myService",
mockMyService);
}
#Test
public void kapow_allGood_success()
{
final String actualResult;
actualResult = classToTest.kapow(mockSomeParameter);
assertNotNull(actualResult); // Not strictly necessary.
assertEquals(
"Blam",
actualResult);
}
}

How to mock a protected method of 3rd party code

Using Mockito I want to mock a property of a class so I can verify the output
public class MyClass extends ThirdPartyFramework {
Output goesHere;
#Override
protected setup(){
goesHere = new Output();
}
//...
}
public abstract class ThirdPartyFramework {
protected setup(){...}
//...
}
I need to inject a mock of the Output class so I can validate that my code wrote the correct output.
But I can't just #InjectMock because the setup() method is called
mid-runtime and overwrites my injection.
And I can't just make setup public in MyClass because the test code I'm working
with is generic and needs to work for all subclasses of
ThirdPartyFramework, so I only have a reference to ThirdPartyFramework, meaning setup() is protected.
Are you set on Mockito? I am asking since Mockito FAQMockito FAQ states that it doesn't support mocking static methods, which I guess you'd need in this case for the setup method to create your mock instead of real Output.
I have used PowerMock for a similar scenario:
whenNew(NewInstanceClass.class).withArguments(any()).thenReturn(mockObject);
which says that each time a NewInstanceClass gets created my mockObject be returned no matter what constructor arguments had been used and who constructed NewInstanceClass at what time.
In PowerMock docs I've also found following example:
PowerMock.expectNew(NewInstanceClass.class).andReturn(mockObject)
Actually you could use it even if you are bound to Mockito, PowerMock contains helpers for Mockito to solve exactly this problem that let you use Mockito for all tests and PowerMock to mock constructing objects. Like this:
whenNew(Output.class).withNoArguments().thenReturn(yourOutputMock);
I ended up solving this by wrapping ThirdPartyFramework and placing that class in the same package as the ThirdPartyFramework class.
That way I could mock the protected methods with Mockito. Then I was able to use #InjectMock to inject a mock of the Output object and control its method calls via that mock.
How about adding a setter for "goesHere" and then have setup() check and only change the value of goesHere if its null. This way you could inject a value in testing that would not be overridden. Something like:
protected void setGoesHere( Output output ){
goesHere = output;
}
#Override
protected void setup(){
if(goesHere != null) goesHere = new Output();
}
Hope this helps.

Appropriate method encapsulation for unit testing

My class contains 14 private methods and 1 public method. The public method calls all the private method directly or indirectly via other private methods.
The public method also has a call to a DAO that queries the database.
I wrote a unit test for the class. Since you can't write unit test for private methods, I changed all the private methods to default access and wrote unit test for them.
I was told that I shouldn't change the encapsulation just for the purpose of testing. But my public method has a call to the DAO and gets its data from the call. Even if I were to write a test for the public method, I'm assuming it would be really long and complicated.
How should I approach this problem. On one hand, I have to write a really complicated test for the public method which accesses a DAO and on the other hand, change the access level of the methods and write short, simple test methods for them. What should I do?
Any suggestions will be greatly appreciated
Purists will tell you that the private methods could be extracted to another helper class providing accessible methods, and they could be right.
But if it makes sense to keep these utility methods inside the class, if the class is not part of a public API and is not intended to be subclassed (it could be final, for example), I don't see any problem with making some of its private methods package-protected or protected. Especially if this non-private visibility is documented, for example with the Guava annotation #VisibleForTesting.
Seems like you have two problems here:
How to test private methods (assuming in Java):
I would look at this question: How do I test a class that has private methods, fields or inner classes?
I personally like Trumpi's response:
The best way to test a private method is via another public method. If this cannot be done, then one of the following conditions is true:
The private method is dead code
There is a design smell near the class that you are testing
The method that you are trying to test should not be private
How to break the dependency of the DAO
You could try to use Dependency Injection to get rid of your dependency on the DAO. Then you can mock out the DAO and inject it into your test case.
The benefit is it truly becomes a unit test and not an integration test.
If it's complicated, it's probably because your class have more than one responsability. Normally, when you have private methods that do different things, is that you could have different classes with public methods that do that for you. Your class will become more easy to read, to test, and you will separate responsability. 14 private methods normally indicates this kind of thing :P
For example, you could have something like
public class LeFooService {
private final OtherServiceForConversion barService;
private final FooDao fooDao;
public LeeFooService(FooDao dao, OtherServiceForConversion barService) {
this.barService = barService;
this.fooDao = dao;
}
public void createAsFoo(Bar bar) throws ConversionException {
Foo foo = convert(bar);
fooDao.create(foo);
}
private Foo convert(Bar bar) {
// lots of conversion stuff, services calling D:
}
}
for testing correctly, you will have to test if conversion was done correctly. Because it's private, you will have to capture the foo sent to FooDao and see if all fields were set correctly. You can use argThat to capture what's sent to fooDao to test the conversion then. Your test would look something like
....
#Test
public void shouldHaveConvertedFooCorrectly() {
// given
Bar bar = mock(Bar.class);
// when
fooService.createAsFoo(bar);
// then
verify(fooDao).create(argThat(fooIsConvertedCorrectly());
}
private ArgumentMatcher<Foo> fooIsConvertedCorrectly() {
return new ArgumentMatcher<Foo>() { /*test stuff*/ };
}
....
But, if you separated the conversion to another class, like this:
public class LeFooService {
private final BarToFooConverter bar2FooConverter;
private final FooDao fooDao;
public LeeFooService(FooDao dao, BarToFooConverter bar2FooConverter) {
this.bar2FooConverter = bar2FooConverter;
this.fooDao = dao;
}
public void createAsFoo(Bar bar) throws ConversionException {
Foo foo = bar2FooConverter.convert(bar);
fooDao.create(foo);
}
}
you will be able to test what's really important to LeeFooService: The flow of the calls. The tests of the conversion from Foo to Bar will be the responsability of the unit tests from BarToFooConverter. An example test of LeeFooService would be
#RunWith(MockitoJUnitRunner.class)
public class LeFooServiceTest {
#Mock
private FooDao fooDao;
#Mock
private BarToFooConverter converter;
#InjectMocks
private LeeFooService service;
#Test(expected = ConversionException.class)
public void shouldForwardConversionException() {
// given
given(converter.convert(Mockito.any(Bar.class))
.willThrown(ConversionException.class);
// when
service.createAsFoo(mock(Bar.class));
// then should have thrown exception
}
#Test
public void shouldCreateConvertedFooAtDatabase() {
// given
Foo convertedFoo = mock(Foo.class);
given(converter.convert(Mockito.any(Bar.class))
.willReturn(convertedFoo);
// when
service.createAsFoo(mock(Bar.class));
// then
verify(fooDao).create(convertedFoo);
}
}
Hope that helped somehow :)
Some links that might be useful:
SOLID
BDD Mockito
As a parent would tell their child: DON'T EXPOSE YOUR PRIVATES!
You don't need to expose your private methods to test them. You can get 100 PERCENT test coverage of your class, including those private methods, without exposing them.
The rub is that some people think the 'unit' in unit testing is the function, when it's really the class.
For example: I have a class with 1 public method:
bool CheckIfPalindrome(string wordToCheck).
Internally, I have private methods to validate the length of the wordToCheck, if it's null, if it's empty, bla bla bla.
But as the tester, I don't need to know or care about how I the developer organized (or will organize) the internal code. I'm testing the implementation of the interface.
'Given the word is "Mike", When CheckIfPalindronme is called, it should return false'
'Given the word is "Mom", When CheckIfPalindronme is called, it should return true'
'Given the word is "", When CheckIfPalindronme is called, it should return false'
'Given the word is null, When CheckIfPalindronme is called, it should throw an error'
If I cover all of the possible inputs and expected outputs, I will be testing your private functions.
This is the basis of TDD / BDD, without this, TDD wouldn't be possible because we would have to wait and see how did you decide to organize your code before we can write our test.
TDD / BDD says write your tests before you even write your code (and it works great btw! It identifies flaws in requirements / design very quickly)
A class containing one public method and 14 private methods, is close to impossible to test. Without having seen it, I would be willing to bet, that it is very un-SOLID. Like JB Nizet says; me and my purist colleaagues would extract most or all private methods to helper classes. The reasons are:
Easy to test
Easy to refactor
Easy to read
Easy to reuse
The reason not to extract:
* A lot!! of classes
* It takes time to extract
* At times, performance issues hinder the pretty-ness of "proper" design.
IMHO extraction of logic should always be considered in case of:
Private methods
Big classes (I usually start to think of it when
the vertical scrollbar appears in my editor winow )
Loops within
loops
The keyword here is Single Responsibility (SRP).

suppress a singleton constructor in java with powermock

I'm trying to unit-test some classes that make use of a Singleton class whose constructor does some things I can't (and shouldn't) do from the unit-test environment. My ideal scenario would be to end up with the constructor completely suppressed and then stub out the other member methods that my test classes invoke. My problem is that I can't seem to get the constructor suppressed.
My understanding of a way to solve this would be something like the following:
public class MySingleton extends AbstractSingletonParent {
public final static MySingleton Only = new MySingleton();
private MySingleton(){
super(someVar); // I want the super-class constructor to not be called
//
//more code I want to avoid
}
public Object stubbedMethod() {}
}
public class ClassToBeTested {
public void SomeMethod(){
Object o = MySingleton.Only.stubbedMethod();
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(MySingleton.class)
public class TestClass {
#Test
public void SomeTest() {
suppress(constructor(MySingleton.class));
mockStatic(MySingleton.class);
PowerMock.replay(MySingleton.class);
// invoke ClassToBeTested, etc
PowerMock.verify(MySingleton.class);
//make some assertions
}
}
Unfortunately during the createMock invocation, the MySingleton constructor is hit, and it still calls the super constructor.
Am I doing something silly? I found an example on the web doing almost exactly this, but it was using a deprecated suppressConstructor method. Despite the deprecation I tried that, too, to no avail...
Is what I'm trying to do possible? If so, what am I doing wrong?
*Edited version now works.
You need to annotate TestClass with the #PrepareForTest annotation so it has a chance to manipulate the bytecode of the singletons.
Also, the superclass ctor supression signature should include somevar's class; right now you're just suppressing the default ctor.
See the #PrepareForTest API docs. Here's a blog post with some more details as well.
FWIW, it's working for me:
#RunWith(PowerMockRunner.class)
#PrepareForTest({EvilBase.class, NicerSingleton.class})
public class TestEvil {
#Test
public void testEvil() {
suppress(constructor(EvilBase.class));
assertEquals(69, EvilBase.getInstance().theMethod());
}
#Test
public void testNice() {
suppress(constructor(EvilBase.class));
suppress(constructor(NicerSingleton.class));
assertEquals(42, NicerSingleton.getInstance().theMethod());
}
}
How about you set the instance field ('only' in your code) of your Singleton with an instance instantiated with the constructor you want (you can do all of this with the Reflection API or dp4j).
The motivating example of a dp4j publication discusses that.
I am not sure what is it that you are doing wrong. But on the design side, i can suggest you look into dependency injection i.e. DI.
For making your code testable, make use of DI. With DI you would pass the singleton class as an constructor argument to your test class. And now since you pass an argument, inside your test case you can create a custom implementation of the AbstractSingleton class and your test case should work fine.
With DI, your code will become more testable.

Categories