I have to unit test some old code that wasn't designed to support unit testing (No DI). Is there a way to mock an object that is being initialized within a public method?
public int method() {
A a = new A(ar1, arg2); //How to mock this?
}
Thanks,
-Abidi
Another option is to refactor the code into
public int method() {
A a = createA(arg1,arg2);
}
A createA(int arg1, int arg2) {
return new A(arg1,arg2);
}
In your test method now you can use Mockito's spy and doAnswer functions to override createA on your test fixture with something along the lines of:
Foo foo = new Foo();
Foo spiedFoo = spy(foo); // a spied version when you can copy the behaviour
doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock inv) throws Throwable {
A a = mock(A.class);
return a;
}
}).when(mySpy).createA(anyInt(), anyInt());
If you have control over the code in question, you can refactor it and make the dependency public, for example by depending on some A-builder. This is probably the best solution, since it makes your class less dependent on A. [Forcing you to decouple your design is one of the main advantages of testing.]
Related
I have DAO class as below:-
// Here I have a class that creates it's own jdbcTemplate using new
// jdbcTemplate(dataSource)
#Repository
public class MyDao {
#Autowired
#Qualifier("db2JdbcTemplate)"
JdbcTemplate jdbcTemplateDB2;
public int insertTable(Company comp) {
int ret = 0;
try {
ret = this.jdbcTemplateDB2(db2DataSource).update(ïnsert into "+ table_name + "(COL1,COL2,...) values (?,?,?,..)",
ps-> {
ps.setString(1, comp.getName);
.......
});
return ret;
} catch (Exception ex) {
// log etc
}
}
}
My Test class is as below:-
#RunWith(MockitoJUnitRunner.class)
public class MyTest {
#Mock
JdbcTemplate jdbcTemplateDB2;
Company comp = new Company(); // this is followed by setter fn to set values.
MyDao mydao = Mockito.mock(MyDao.class);
Mockito.when(((jdbcTemplateDB2.update(any(String.class),
any(PreparedStatement.class))).thenReturn(2);
ReflectionUtils.setField(mydao, "jdbcTemplateDB2", jdbcTemplateDB2);
int bVal = mydao.insertTable(cmp);
}
}
iVal is not getting value 2. It is making original update call and returning value like 0/1.
Getting UnnecessaryStubbingException. If I make lenient() call the exception goes away but result is same (expected as lenient only removes warning).
How to make this stubbing work?
In this line: MyDao mydao = Mockito.mock(MyDao.class); you're creating a mock object, which overrides your actual class'x behavior, but you seem to want to test this very class, so it doesn't make any sense. What you need to do is: create an actual instance of the class and inject mocks into it (you're using ReflectionUtils to do that, but Mockito has it's own, simple mechanism to do that).
#Mock
JdbcTemplate jdbcTemplateDB2;
// this tells mockito to create the object and inject mocks into it
#InjectMocks
MyDao myDao;
#Test
void test() {
// define the behavior for the mock
when(jdbcTemplateDB2.update(...)).thenReturn(2);
// call the actual method of the tested class object (not a mock)
int result = myDao.insertTable(...);
// perform assertions (e.g. verify the result value)
}
Recommended reading: Mockito documentation (very comprehensive, yet simple).
Important note: field injection is discouraged.
Class that i want to mock:
TestClass.java
public class testClass(){
public String getDescription(String input){
String value = this.getDetails(input); // i am not going to change this line, hence want to mock this.
//below this i have some complexity logic, which i would like to fix cyclomatic complexity issue
}
private String getDetails(String input){
return "More details for the "+input;
}
}
My questions is how do i mock "this.getDetails(input)" to return some string for testing purpose?
If you've got a class that is big and complex enough that you need to mock a small piece of it, take that as a hint that you're violating the Single Responsibility Principle and properly split up the classes. If you use dependency injection, you can then supply whatever implementation you'd like.
public class TestClass {
/**
* Computes a detail string based on an input. Supply this in the constructor
* for full DI, relax visibility, or add a setter.
*/
private final Function<String, String> detailFunction;
public String getDescription(String input){
String value = detailFunction.apply(input);
// ...
}
}
As a lightweight alternative, you can test an override or spy of your actual class.
#Test public void testTestClassWithOverride() {
TestClass instanceUnderTest = new TestClass() {
#Override public String getDescription(String input) {
return "Predictable value";
}
};
// test your instanceUnderTest here
}
#Test public void testTestClassWithSpy() {
TestClass spyUnderTest = Mockito.spy(new TestClass());
doReturn("Predictable value").when(spyUnderTest).getDescription(anyString());
// test your spyUnderTest here
}
Bear in mind that, though this is an option for you, it shouldn't be your first option: Rather than testing your actual class, you're testing a one-off variant of it, and you've made it so other consumers can subclass your TestClass as well. If possible, write the flexibility you need into the class itself and treat your test as a consumer that plays by the same rules.
First of all, it is a bad practice to make a so-called "partials mocks". This illustrates that your code doesn't follow single responsibility principle that leads to your code being not (or hardly) testable.
I would suggest you to extract getDescription method from your class and use it indirectly via dependency inversion or more concrete - dependency injection (for instance by employing Spring Framework):
public class TestClass() {
private DetailsServiceProvider detailsServiceProvider;
public TestClass(DetailsServiceProvider detailsServiceProvider) {
this.detailsServiceProvider = detailsServiceProvider;
}
public String getDescription(String input) {
String value = detailsServiceProvider.getDetails(input); // i am not going to change this line, hence want to mock this.
//below this i have some complexity logic, which i would like to fix cyclomatic complexity issue
}
}
public interface DetailsServiceProvider {
String getDetails(String input);
}
public class DetailsServiceProviderImpl implements DetailsServiceProvider{
#Override
public String getDetails(String input) {
return "More details for the "+input;
}
}
Then in your test, you could simply:
#Test
public void test() {
DetailsServiceProvider mockedProvider = Mockito.mock(DetailsServiceProvider.class);
//TODO: add scenarios for the mocked object
TestClass target = new TestClass(mockedProvider);
String description = target.getDescription();
//TODO: add assertions
}
If you do not want to struggle with the preferred approach you could use #Spy in Mockito. This will create exactly what you want - a partial mock for your object where part of the methods will be real and another part - mocks:
#Test
public void test() {
TestClass partialMockedObject = Mockito.spy(new TestClass());
Mockito.doReturn("test details").when(partialMockedObject).getDetails();
String description = partialMockedObject.getDescription();
//TODO: add assertions
}
Again, this method is not desired but can be used if no other options are given. Note that this requires getDetails() to be visible in tests, meaning that the private modifier won't work here.
I am making a framework for making fractals in processing, however, I need to use functions as parameters for a constructor of a class.
Something like:
class Fractal {
String name;
void initialize;
Fractal(String Name, void setup) {
...
}
}
I'm going to guess you're coming from a JavaScript background?
Traditionally, Java didn't really have a way to do this. Instead you'd pass an anonymous instance of an interface, like this:
interface Runner{
public void run();
}
class Fractal {
String name;
Runner initialize;
Fractal(String name, Runner setup) {
...
}
}
Runner r = new Runner(){
public void run(){
// whatever
}
}
Fractal fractal = new Fractal("name here", r);
Note that Java provides a Runnable interface that you can use instead of creating your own, but I wanted to spell it out here to make it more obvious.
As of Java 8, you can pass a reference to a function as a parameter. This is called a lambda function. Googling "Java lambda function" will return a ton of results.
From this answer:
public void pass() {
run(()-> System.out.println("Hello world"));
}
public void run(Runnable function) {
function.run();
}
Depending on how you're using Processing, you might be stuck with the first approach though, since I don't think the Processing editor supports Java 8 yet.
Hi i am trying to mock dao layer
my application has some class hire achy like this Application->parser->dao(interface)->dao implementation class
my problem is when i am mocking dao interface or daoimp class using mockito
in my test case they are not working simply test case going to db how to do make our test case to use these mocked objects
#RunWith(MockitoJUnitRunner.class)
public class CsvDataLoadServiceImplTest {
#Mock private MeteringDataDao meteringDataDao;
List<Object> persistedList;
Object meteringData;
List<Object> s=new ArrayList<Object>();
#SuppressWarnings({ "rawtypes", "unchecked" })
#Before public void setup(){
Mockito.doAnswer(new Answer<List<Object>>() {
#Override
public List<Object> answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
System.out.println("persist all");
if(persistedList == null){
persistedList = (List)args[0];
}
else
persistedList.addAll((List)args[0]);
return null;
}}).when(meteringDataDao).persistAll(anyList());
Mockito.doAnswer(new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
if(meteringData == null)
meteringData = (List)args[0];
return true;
}}).when(meteringDataDao).persist(anyObject());
}
#After public void tearDown(){
persistedList = null;
meteringData = null;
}
#Test
public void testDataAccuricy(){
CsvDataLoadService csvDataLoadService =new CsvDataLoadServiceImpl();
csvDataLoadService.loadRackspaceCsvData();
}
}
CsvDataLoadService csvDataLoadService = new CsvDataLoadServiceImpl();
You're constructing an instance of the service, but this instance doesn't use the DAO you mocked. It uses another one. You need something like
CsvDataLoadService csvDataLoadService =
new CsvDataLoadServiceImpl(meteringDataDao);
Your question is a little badly phrased, so sorry if I appear to have misunderstood you.
#JBNizet answer is correct, you're not using the mocked object, but rather than changing the code for a test you should simply change the test. This is always a best practice when writing your tests.
You haven't assigned the mocked object to the service, so I'm assuming that the MeteringDataDao object is actually instantiated inside the class you're attempting to test?
If so, then you will need something more powerful than Mockito (Unless you want to reproduce the capabilities of a more powerful already existing library). I would suggest PowerMockito, which I have used in the past for something exactly like this.
A good example of using powermockito to mock the constructor of a class can be seen in a few answers on SO already, so I'll just link to them rather than try and re-explain their already clear answers:
Powermock constructor mocking has no effect on the instantiated object
mockito mock a constructor with parameter
I have a method as follows
private void validate(String schemaName){
....
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);**strong text**
Source schemaFile = new SteamSource(getClass().getClassLoader().getResourceAsStream(schemaName));
Schema schema = factory.newSchema(schemaFile);
....
}
This method get called from another method which I need to test(Using easymock and powermock). I'm struggling to mock following line
Source schemaFile = new SteamSource(getClass().getClassLoader().getResourceAsStream(schemaName));
Can someone give me a clue on this?
Current Status
Following is the mock statement
expectNew(StreamSource.class, anyObject(InputStream.class)).andReturn(mockedobject);
Powermock.replay(mockedobject, StreamSrouce.class);
This throws the following exception.
org.powermock.reflect.exceptions.TooManyConstructorsFoundException: Several matching constructors found, please specify the argument parameter types so that PowerMock can determine which method you're referring to.
Matching constructors in class javax.xml.transform.stream.StreamSource were:
I think you can do it using powermock in the following way (I'm just following the tutorial here):
Let's say you're class looks like this:
public class MyClass {
private void validate(String schemaName) {
....
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);**strong text**
Source schemaFile = new SteamSource(getClass().getClassLoader().getResourceAsStream(schemaName));
Schema schema = factory.newSchema(schemaFile);
....
}
}
You should create a test class like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class MyClassTest {
private MyClass testedClass = new MyClass();
private ClassLoader mockedClassLoader = createMock(ClassLoader.class);
private InputStream mockedInputStream = createMock(InputStream.class);
#Before
public void setUp() {
PowerMock.createPartialMock(MyClass.class, "getClass");
expect(testedClass.getClass()).andReturn(mockedClassLoader);
expected(mockedClassLoader.getResourceAsStream(***You string***)).andReturn(mockedInputStream);
replayAll(); // Not sure if that's the name of the method - you need to call replay on all mocks
}
#Test
public void testValidate() {
// Run your test logic here
}
}
Please excuse me if some of the easymock methods I used are named a bit differently. But this is the basic idea.
I think you need one or a combination of the following. Use Powermock constructor mocking for the new StreamSource as documented here: Powermock MockConstructor. You will probably also need to use a mock for SchemaFactory which mean you will need to mock the static factory method call via Powermock: MockStatic