Is there an easy way, using Mockito, to load a mock class when another is requested OR to override the test ClassLoader?
Basically I have a class Foo that has a member "ClassA" in it. I want to replace to use "TestClassA" instead of "ClassA" during testing. I don't want to use dependency injection because it doesn't make any sense for actual operation. (It can never be anything other than ClassA)
Can I do this?
It can never be anything other than ClassA
...except that it is, in your test. Test code is real code, and though that doesn't mean it should sneak into your production application, it does mean that you need to write in the flexibility you need for all of its use cases, and that includes testing.
Mockito works via subclasses: A mockFoo created by mock(Foo.class) or #Mock Foo mockFoo is actually a proxy subclass Mockito created that overrides each of Foo's methods. As you can tell from that description, Mockito thus cannot change the behavior of every Foo object and especially cannot change the type of the object returned from new Foo().
You have two options, that I can see:
Accept a ClassA or InterfaceA instance in one of your constructors. If you put your tests in the same Java package as your class under test (even in a different source tree), you can even make the constructor package-private, or keep it private and create a static factory method like createForTest(ClassA).
Example:
public class ConsumerToTest {
private final ClassA classA;
/** For public use. */
public ConsumerToTest() {
this(new ClassA());
}
/** For use in tests. */
ConsumerToTest(ClassA class) {
this.classA = classA;
}
// ...
}
Use PowerMock, which has a Mockito integration known as PowerMockito. Though Mockito uses pure proxy subclasses and code generation, PowerMockito actually rewrites the bytecode of the system-under-test. This means that you can mock static methods and constructors that Mockito couldn't adjust on its own through polymorphism.
Personally, I very much prefer solution 1: The code is yours to control, and as long as you're clear that your test is a first-class consumer of your system-under-test, you're free to design it to be testable in the first place.
Doing it by constructor is what I prefer.
For example
public class Foo {
private ClassA classA;
public Foo(ClassA classA) {
this.classA = classA;
}
}
public class FooTest {
private Foo foo;
#before
public void setup() {
foo = new Foo(Mockito.mock(ClassA.class);
}
}
It's really simple to do this using Mockito.
public class Foo {
private ClassA classA;
}
Test will look like this:
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
#Mock
private ClassA classA;
#InjectMocks
private Foo foo = new Foo();
//Test methods
}
That's it, you have mocked ClassA!
Related
I have a init() method that use injected private instance<>. How can I test this class using JUnit or Mockito? I tried to make some fake class and add them to a list and set this list to my private field but I have this error
java.lang.IllegalArgumentException: Can not set javax.enterprise.inject.Instance field ......
MyClass is:
#Singleton
#Startup
public class HandlerManager {
#Any
#Inject
private Instance<RollbackHandler<RollbackData>> handlers;
private RollbackHandler<RollbackData> rollbackHandler;
#PostConstruct
public void init() {
for (RollbackHandler<RollbackData> bean : handlers) {
//do something
}
}
}
Any annotation is not processed by frameworks, unless you use custom work. you will have to define all those dependencies as mocks in your test using #Mock and call injectMocks() from before test methods such as setup(). It is a multi part problem.
Use constructor injection, field injection is evil. you still will be able to annotate your constructor with #Inject.
when(provider.iterator()).thenReturn(list.iterator);
works for me.
You can create a temporary list with concrete implementations of the RollbackHandler, and mock the iterator() method of your Instance<RollbackHandler<RollbackData>> object so that it returns the iterator of the temporary list.
Example:
private void mockIterator() {
Instance<RollbackHandler<RollbackData>> handlers = mock(Instance.class);
List<RollbackHandler<RollbackData>> handlersList = Collections.singletonList(new RollbackHandlerImpl<>());
when(handlers.iterator()).thenReturn(handlersList.iterator());
}
I am having a hard time getting this one piece of mocking figured out for my unit tests. The classes in question are all part of legacy code that I don't really have the option of changing right now (I am hoping to be able to do some refactoring in the future, but need tests now).
Here are the two classes that I am dealing with, and the specific part I am having trouble with. Class A declares an object using new and then class B uses the object. I am trying to mock the object but I keep getting the real version of it instead of the mocked version.
public class B extends A(){
...
int x = problemObj.doMethod();
}
public class A(){
...
ProblemObj problemObj = new ProblemObj();
}
Here is my test class.
#RunWith(PowerMockRunner.class)
#PrepareForTest({A.class, B.class})
public class ATest(){
private ProblemObj problemObjMock;
#Before
public void setUp(){
problemObj = PowerMockito.Mock(ProblemObj.class);
}
#Test
public void test(){
PowerMockito.whenNew(ProblemObj.class).withNoArguments().thenReturn(problemObj);
...//rest of test below here
}
}
I have done other whenNew mocking in tests and set it up the same way as this. But for some reason this object being in the superclass is really throwing me off.
Versions used are Junit:4.11, Mockito:1.9.5, Powermock: 1.6.6
I want to test SomeClass methods.
For that, I need SomeClass instance in every test so I'm using #Before annotation and initiate an instance of SomeClass named SC.
The problem is:- How can I test the constructor function after I already use it? It doesn't make sense.
Additional question:- The constructor can get number of arguments and they can influnce the methods outputs, should I mock this class instead of creating an instance of it?
public class SomeClassTest {
SomeClass SC;
#Before
public void initlize() throws IOException{
SC= new SomeClass (argument1,argument2,..);
}
#Test
public void ConstructorTest() {
}
Just don't use the object SC in your ConstructorTest. If you wan't to test a certain outcome from the construction of a SomeClass object with certain parameters then just construct it as such within your ConstructorTest and then assert the relevant outcomes you expect on the newly constructed object.
And no you shouldn't be mocking this class. The test is for testing this class so if you mock it's behaviour then you aren't really testing anything.
Hi I have a class which the invoke the run() method of a thread from the constructor of the class by calling the start() method , So please help me to Stubs the so to write the junit test cases . The class is as follows
public class MyClass extends Thread {
Student st=null;
University uni= new University();
public MyClass(Student st) {
this.st=st;
start();
}
public void run() {
uni.calculate(st);
}
}
Thanks
Take a look at the discussion here:
Testing Constructor With Powermock
It discusses sub-classing and overriding.
In general it should be considered bad practice to have to mock the class under test in order to test it. It is also hard to do since most mocking frameworks will not allow mocking a single method once in the class under test since they create wrapping proxies.
Hi I am new to unit testing. Is it possible to access methods that are private?
A very simple example
ObjectA
----------
File file;
private void setupFile (){
//do something
file = "C:\file.dat"
}
In TestCase
File sth = ObjectA.setupFile();
assertNotNull(sth);
I am unable to test whether the file variable is null in method ObjectA.setup()
as I cannot run ObjectA.setupFile()
I am not sure about whether doing like this make sense in terms of unit testing.
So is that a better practice to write every method returning sth and set them public for easier unit testing?
Thanks in advance
In general, you should avoid changing the access of a method/field to enable testing. If you do this then you risk developers using the method directly.
However, if you do need to, then making it protected as Deco says is a good way, so it's accessible from the JUnit tests. If you do this, make sure that it is well documented that this is an method for internal use.
A better way is to test the behaviour of the public methods; you shouldn't care about internal implementation details of a class, so you should only be testing public methods. It's hard to tell from your code, but presumably, the setupFile() has effects later on other methods, so you can test those effects, not the fact that file is not null.
External dependencies (such as dependencies on file system, environment variables) can be worked around in your tests, or injected directly into the class. For the general principle, see my answer to How to test code dependent on environment variables using JUnit?
If it is not absolutely necessary to have the method as private, you can have it as package private (i.e. default access) so that you can call it directly in a JUnit test.
Package private methods can only be used in the package that they are declared, and do not become part of the API of the class. You declare a method package private by putting no modifier on it's declaration.
Here's an example to demonstrate:
public class MyClass() {
int foo;
public MyClass() {
this.foo = 0;
}
void notSoComplexCalculationMethod(int a) {
foo = a * 2;
}
//Other methods here . . .
}
public class MyClassTest extends TestCase {
private MyClass myClass;
protected void setUp() {
super.setUp();
myClass = new MyClass();
}
public void testNotSoComplexCalculationMethod() {
int a = 2;
assertEquals(4, myClass.notSoComplexCalculationMethod(a));
//Unit test passes, yay! Now you've tested a package private method.
}
}