I have tested that incredible feature provided by whenNew some days ago, that allows us to "intercept" constructor calls of any class inside tested environment and return eg. mocked instance of given class. I was wondering what are principles behind this? My first thought was a bytecode manipulation in order to inject proper code blocks to contructor but hey - constructors does not return created instance so this is obviously not an answer.
What would it be then? AOP - intercepting contructor calls and replacing it with return given object statements?
Powermock modifies the bytecode in the calling class (the one with new SomeMockedClass(...)) so that it recovers and uses the mock instance passed into whenNew.
This is not the only way it could be implemented by a mocking library, though. JMockit also mocks constructors, but it does it by modifying the actual constructor instead (which still returns void, of course).
Related
For example, the class to be tested is
public class toBeTested {
private Object variable;
public toBeTested(){
variable = someFactory(); // What if this someFactory() sends internet request?
// Can I mock "variable" without calling
// someFactory() in testing?
}
public void doSomething(){
...
Object returnedValue = variable.someMethod(); // In testing, can I mock the behavior of
// this someMethod() method when
// "variable" is a private instance
// variable that is not injected?
Object localVariable = new SomeClass(); // Can I mock this "localVariable" in
// testing?
...
}
}
My questions are as stated in the comments above.
In short, how to mock the variables that are not injected but created inside the to-be-tested class?
Thanks in advance!
Your question is more about the design, the design of your class is wrong and it is not testable, It is not easy (and sometimes it is not possible at all) to write a unit test for a method and class that have been developed before. Actually one of the great benefit of TDD(Test Driven Development) is that it helps the developer to develop their component in a testable way.
Your class would have not been developed this way if its test had been written first. In fact one of the inevitable thing that you should do when you are writing test for your component is refactoring. So here to refactor your component to a testable component you should pass factory to your class's constructor as a parameter.
And what about localVariable:
It really depends on your situation and what you expect from your unit to do (here your unit is doSomething method). If it is a variable that you expext from your method to create as part of its task and it should be created based on some logic in method in each call, there is no problem let it be there, but if it provides some other logic to your method and can be passed as parameter to your class you can pass it as parameter to your class's cunstructor.
One more thing, be carefull when you are doing refactoring there will be many other components that use your component, you should do your refactoring step by step and you should not change the logic of your method.
To add another perspective: If faced with situations in which you have to test a given class and aren't permitted to change the class you need to test, you have the option to use a framework like PowerMock (https://github.com/powermock/powermock) that offers enhanced mocking capabilities.
But be aware that using PowerMock for the sole purpose of justifying hard to test code is not advisable. Tashkhisi's answer is by far the better general purpose approach.
I'm trying to unit-test an abstract class, therefore need to provide a mock implementation to the class' abstract methods.
I think I'm in a niche situation (!) since neither #Mock or #Spy seem to help.
tried Mockito.mock(SimpleClient.class, Mockito.CALLS_REAL_METHODS) but this totally shatters my abstract class (creates it without calling the constructor, running into NPE)
tried #Spy but this either requires an instance of the real class (which I cannot provide since it's abstract duh), or, it will attempt to call a no-arg constructor which doesn't exist.
(Context, although you should not need it: the class is a messaging client e.g. has sendMessage() and abstract onMessage() methods, and obviously I need to use the real implementation of sendMessage() and mock the callback abstract onMessage())
I found the following
to go the first approach (Mockito.mock), they have added the ability to construct an underlying real object properly using an arbitrary constructor (And hopefully after that, Moquito goes on to "stub" each method as you express expectations on it, like the below):
MyClass mock = Mockito.mock(MyClass.class, Mockito.withSettings()
.useConstructor("stringArg", 17)
.defaultAnswer(Mockito.CALLS_REAL_METHODS));
// ...
Mockito.when(mock.onMyAbstractMethod(Mockito.anyInt())).then(
invocation -> mock.callAnotherRealMethodOnTheMock(invocation.getArgument(0)));
to go the second approach indeed a #Spy needs a created instance of the class, so in that case you really need to subclass it first.
Extra note: a separate issue, ugly as well, happens if say onMyAbstractMethod returns void, in that case the Mockito.when... syntax doesn't work due to a language limitation it seems, a fact which is poorly documented. One needs to do it the other way around and say:
Mockito.doAnswer(invocation -> mock.callAnotherRealMethodOnTheMock(invocation.getArgument(0)))
.when(mock).onMyAbstractMethod(1);
So I'm trying to test a method methodUnderTest which is something like this:
methodUnderTest{
//Other stuff that works nice
this.setterMethod(OtherClass.methodThatErrors(arg1));
}
So I'm trying to avoid that static method call methodThatErrors.
What I'm doing so far:
ClassUnderTest spy = Mockito.spy(objectOfClassUnderTest);
Mockito.doNothing().when(spy).setterMethod(Mockito.any(OtherClass.class));
However this does not work, the method is still being called. I would've thought that it shouldn't call the argument method at all because I've written any for the argument of setterMethod. So how can I prevent this call using Mockito, not PowerMockito.
Edit:
So I managed to mock it by moving the static method call like so:
methodUnderTest{
this.extraSetterMethod(arg1);
}
extraSetterMethod(arg1){
this.setterMethod(OtherClass.methodThatErrors(arg1));
}
I don't really like this solution because it's adding several extra lines of code (even more with javadoc) which just makes the class messier.
The problem here is that the value is coming directly from the static method, and not the setter itself. Whatever value it's getting is coming from the real invocation of the method itself. Mocking out the call to the setter has no effect; it's not the result of the setter that's in error.
This is a scenario in which you have to make a hard decision:
Introduce a parameter to the method so that the call can be easier to mock, or
Use PowerMockito to mock out the call.
I strongly encourage the latter, especially if you're dealing with a legacy code base which is not very forgiving to a signature change.
I am developing an interpreter and want to do internal testing of an "execute" method that interprets a model. The execute method doesn't have input or output, so the only way to test the method (at least from what I know) is to mock the internal method calls to see that they are executed in the right order.
Currently I have the following classes:
ExecutableInstance - model class that can be executed.
ExecutableInstanceFactory - singleton class (implemented as an enum) that creates executable instances, with different methods depending on the parameters it is given.
ModelAnalyzer - singleton class that contains methods to analyze the model
The interpreter calls the execute() method of the ExecutableInstance class, which then calls the ModelAnalyzer to understand the internal executable instances in the model. It then creates new ExecutableInstances using the ExecutableInstanceFactory and then calls their execute() method depending on how the model is defined.
My idea is to mock the ExecutableInstanceFactory class so that it returns mock ExecutableInstaces which I can then test for execution order. But this would mean that I have to inject the ExecutableInstanceFactory into the ExecutableInstance. Since it is a singleton, it would be dumb and stupid to pass it as a parameter. I thought of using Google's Guice for DI... but I'm stuck trying to do this.
Is my direction correct? If so, how should this be implemented?
I would make a few smaller methods out of this execute method. For example - one method for parsing which returns something to the execute method, then another one which does something with the returned data and returns other data etc. Then you would not have to test the Execute method, only the smaller ones. This will also allow you to detect bugs easier.
The execute method doesn't have input or output
So behaviour should be verified on the class' collaborators (use mocks).
Since it is a singleton, it would be dumb and stupid to pass it as a parameter.
The fact that you have problems testing shows you flaws in your design. Get rid of a singleton and inject the collaborators.
Is there a way to mock object construction using JMock in Java?
For example, if I have a method as such:
public Object createObject(String objectType) {
if(objectType.equals("Integer") {
return new Integer();
} else if (objectType.equals("String") {
return new String();
}
}
...is there a way to mock out the expectation of the object construction in a test method?
I'd like to be able to place expectations that certain constructors are being called, rather than having an extra bit of code to check the type (as it won't always be as convoluted and simple as my example).
So instead of:
assertTrue(a.createObject() instanceof Integer);
I could have an expectation of the certain constructor being called. Just to make it a bit cleaner, and express what is actually being tested in a more readable way.
Please excuse the simple example, the actual problem I'm working on is a bit more complicated, but having the expectation would simplify it.
For a bit more background:
I have a simple factory method, which creates wrapper objects. The objects being wrapped can require parameters which are difficult to obtain in a test class (it's pre-existing code), so it is difficult to construct them.
Perhaps closer to what I'm actually looking for is: is there a way to mock an entire class (using CGLib) in one fell swoop, without specifying every method to stub out?
So the mock is being wrapped in a constructor, so obviously methods can be called on it, is JMock capable of dynamically mocking out each method?
My guess is no, as that would be pretty complicated. But knowing I'm barking up the wrong tree is valuable too :-)
The only thing I can think of is to have the create method on at factory object, which you would than mock.
But in terms of mocking a constructor call, no. Mock objects presuppose the existence of the object, whereas a constructor presuppose that the object doesn't exist. At least in java where allocation and initialization happen together.
jmockit can do this.
See my answer in https://stackoverflow.com/questions/22697#93675
Alas, I think I'm guilty of asking the wrong question.
The simple factory I was trying to test looked something like:
public Wrapper wrapObject(Object toWrap) {
if(toWrap instanceof ClassA) {
return new Wrapper((ClassA) toWrap);
} else if (toWrap instanceof ClassB) {
return new Wrapper((ClassB) toWrap);
} // etc
else {
return null;
}
}
I was asking the question how to find if "new ClassAWrapper( )" was called because the object toWrap was hard to obtain in an isolated test. And the wrapper (if it can even be called that) is kind of weird as it uses the same class to wrap different objects, just uses different constructors[1]. I suspect that if I had asked the question a bit better, I would have quickly received the answer:
"You should mock Object toWrap to match the instances you're testing for in different test methods, and inspect the resulting Wrapper object to find the correct type is returned... and hope you're lucky enough that you don't have to mock out the world to create the different instances ;-)"
I now have an okay solution to the immediate problem, thanks!
[1] opening up the question of whether this should be refactored is well out of the scope of my current problem :-)
Are you familiar with Dependency Injection?
If no, then you ceartanly would benefit from learning about that concept. I guess the good-old Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler will serve as a good introduction.
With Dependency Injection (DI), you would have a DI container object, that is able to create all kinds of classes for you. Then your object would make use of the DI container to instanciate classes and you would mock the DI container to test that the class creates instances of expected classes.
Dependency Injection or Inversion of Control.
Alternatively, use the Abstract Factory design pattern for all the objects that you create. When you are in Unit Test mode, inject an Testing Factory which will tell you what are you creating, then include the assertion code in the Testing Factory to check the results (inversion of control).
To leave your code as clean as possible create an internal protected interface, implement the interface (your factory) with the production code as an internal class. Add a static variable type of your interface initialized to your default factory. Add static setter for the factory and you are done.
In your test code (must be in the same package, otherwise the internal interface must be public), create an anonymous or internal class with the assertion code and the test code. Then in your test, initialize the target class, assign (inject) the test factory, and run the methods of your target class.
I hope there is none.
Mocks are supposed to mock interfaces, which have no constructors... just methods.
Something seems to be amiss in your approach to testing here. Any reason why you need to test that explicit constructors are being called ?
Asserting the type of returned object seems okay for testing factory implementations. Treat createObject as a blackbox.. examine what it returns but dont micromanage how it does it. No one likes that :)
Update on the Update: Ouch! Desperate measures for desperate times eh? I'd be surprised if JMock allows that... as I said it works on interfaces.. not concrete types.
So
Either try and expend some effort on getting those pesky input objects 'instantiable' under the test harness. Go Bottom up in your approach.
If that is infeasible, manually test it out with breakpoints (I know it sucks). Then stick a "Touch it at your own risk" comment in a visible zone in the source file and move ahead. Fight another day.