I have a Class that has a field that gets set through a spring bean and is annotated with #Autowired like so:
public class Foo {
....
#Autowired
private Bar bar;
....
}
I now want to setup a JUnit test that tests some functionality that at some point will create a Foo object. I am not in control of when this Foo object is generated. What is the easiest way to mock this object so that anytime Foo gets instantiated, this object get populated with the mocked item? I am using a 3rd party library to mock the Bar object nicely, so I would prefer to do all of this in the Java test class without using xml files.
Everything I have found online seems to either involve creating an xml file or mocking a specific instance of the Class. Thank you all for your help!
I would like something like the following:
public class Test {
private Bar mockedBar = createBar();
// somehow set 'mockedBar' so that any Foo object
// created always contains mockedBar
}
I have written uch test with help of JMOCKIT,
Please read it might help you.
You just need to create object with overriding required methods.
Then use
Deencapsulation.setfield(FIXTURE,new Bar(){
//#Override you methods
});
FIXTURE is Object in which you want Bar instance available with mocked methods.
With the JMockit mocking library, you could simply declare a mock field as #Capturing Bar anyBar in your test class. This should cause any current or future Bar instances to be mocked, even if they belong to some subclass of Bar.
Related
I meet a question about the mock private method in a injected mock annotated class. My code is like following
public class foo {
#Autowired
fooBean fooBean;
public void method1() {
this.method2();
}
private void method2() {
fooBean.someMethod();
system.out.println("Hello world");
}
}
when I create a UT class with powermockito, the foo class should be #injectMocks, since the fooBean should be injected as mock class. But when foo class is marked as #injectMocks, it can't be mock its private method using like "doReturn("xxx").when(foo,"method2")", it will raise error about this can not be applied to injectMocks.
It is blocked. Don't know how to continue.
TLDR; you cannot use InjectMocks to mock a private method.
You should mock out implementation details and focus on the expected behaviour of the application. It is important as well that the private methods are not doing core testing logic in your java project.
Focus on writing functions such that the testing is not hindered by the private method. If it is not possible, it is worth asking what is the private method doing that is so valuable to your function and why it has to be private.
There are other ways to test private methods - You could use the Reflections java library, this would let you stop methods at runtime and inject specific values into them. But, again, this is finding a solution to a problem that does not need to exist.
Is it possible to instantiate a class with a complex constructor without mocking or calling its constructor? This would be useful because the unit test class shouldn't need to change every time a new dependency was added to the service.
Mocking the service solves the problem by creating a new implementation of the class, with empty method overrides, but this isn't an instance of the implementation. This is a problem because any time a method in the mocked service is called, Mockito has to be told to call the real method. Instead, an actual implementation of the service would be preferred.
For example:
class ComplexService {
private Service service1;
private Service service2;
private Service service3;
private Service service4;
private Service service5;
ComplexConstructor(Service service1, Service service2, Service service3, Service service4, Service service5) {
this.service1 = service1;
this.service2 = service2;
this.service3 = service3;
this.service4 = service4;
this.service5 = service5;
}
boolean methodToTest() {
return service1.get();
}
}
In the unit test class, is it possible to have an instantiation of a implementation without having to call its constructor?
public class ComplexConostructorTest {
private ComplexConstructor complexConstructor;
private Service serviceMock;
#Before
public void init() {
/*
Somehow create implementation of complexConstructor
without calling constructor
. . .
*/
// Mock dependency
ReflectionTestUtils.setField(complexConstructor,
"service1",
serviceMock = Mockito.mock(Service.class));
}
#Test
public void service1Test() {
when(serviceMock.get())
.thenReturn(true);
assertTrue(complexConstructor.methodToTest());
}
}
Edit
It is possible using reflection, I was hoping there was a built in way in JUnit or Mockito to achieve the same thing. Here is how to do it using reflection.
#Before
public void init() {
Constructor<?> constructor = ComplexConstructor.class.getConstructors()[0];
complexConstructor = (ComplexConstructor) constructor.newInstance(new Object[constructor.getParameterCount()]);
// Mock dependency
ReflectionTestUtils.setField(complexConstructor,
"service1",
serviceMock = Mockito.mock(Service.class));
}
This is not possible, as far as I know, but you can simply add a simpler Constructor to your class and use that for testing. On the other hand, if the test tests the object in a state that is different to what it will be in the app, I'm not sure how good such a test would be.
You can, but you probably don't want to:
ComplexConstructor partialMock =
Mockito.mock(ComplexConstructor.class, CALLS_REAL_METHODS);
This "partial mock" instance will not have its constructor or field initializers called, but all calls to the system under test will invoke the class's real behavior. (Technically the class will also have its equals and hashCode overridden for Mockito's purposes, and the class will be a generated subclass of ComplexConstructor instead of ComplexConstructor itself.)
In this way, you can be insulated from the constructor, but because you are suppressing an arbitrary subset of the class-under-test's behavior it is much more difficult to determine exactly what you're testing in order to be confident the system works because the test passes. That should be your main goal in testing, and it may be difficult to achieve that with partial mocks. Colleagues or collaborators may rightly observe that you shouldn't mock your system under test for exactly this reason.
Though personally I don't think it's wrong or unexpected for you to need to change your unit tests to supply mocks when needed, you could create a factory separate from your test that supplies testing instances of ComplexConstructor, or consider using a dependency injection framework that automatically supplies mocks to your system under test.
Looks like you are mixing up several terms and concepts. Let me help you understand them better.
This would be useful because the unit test class shouldn't need to change every time a new dependency was added to the service.
Your class has a number of dependencies, that are provided via the constructor. If you are writing unit test your aim is only to test this dependent class, all dependencies should be mocked. That's why it is called unit testing. This means that with every new dependency of your class the test should be updated by adding new mock and its mocked behaviour.
Mockito has to be told to call the real method. Instead, an actual implementation of the service would be preferred.
Consider integration tests, in this case, you can mock only some amount of dependencies while others will work as intended or "real" until you mock them of course. However, if you want just to avoid supporting tests then it is not the right approach.
Please don't try to hack your tested class from your test by reflection. This can lead to wrong test results, waste of time and overall disappointment :) Mocking libraries like PowerMock and JMockit provide any kind of hacks, like ones you've tried to implement yourself and are in general too powerful.
With Great Power Comes Great Responsibility
You can create helper methods as part of your test code, for example some factory methods with descriptive names that construct the object. For example, make_default_ComplexService and more the like, just as needed by your tests. The tests could then use these methods, and if the constructor changes, you will in many cases only have to update the helper methods and not all of the tests. This approach is generic enough to also separate your test from drastic changes like turning the "constructor with parameters" approach into the "non-argument constructor with lots of setters" approach.
This approach will reduce maintenance effort for your tests, you will still use the original constructor (because it is called by the factory) rather than some fake constructor, and your test code might even be more readable than with the direct constructor's calls if the factory methods' names are well chosen.
You could add a parameterless constructor to your class and create setter for all your fields.
class ComplexService {
private Service service1;
private Service service2;
private Service service3;
private Service service4;
private Service service5;
public ComplexService(){
super();
}
...
public void setService1(Service service1){
this.service1 = service1;
}
//for other fields too
...
}
In your test you call it like:
myService = new ComplexService()
myService.setService1(service1);
...
My void method changes boolean variable value in the class. How do DI check that?
I have:
mocked class object
called the method with proper parameters
checked the instance variable
But that doesn't change the value of instance variable. How do I do this?
ReferenceLettersBean rf = Mockito.mock(ReferenceLettersBean.class);
rf.setBoolcheck(false);
Mockito.doNothing().when(rf).checkForDuplicates(anyString(), anyString(), anyString());
rf.checkForDuplicates("abcd#emal.com","abd#gmail.com","abcd#gmail.com");
assertEquals(true,rf.getBoolcheck());
DON'T mock the class you are trying to test.
DO mock the classes that interact with the class you are trying to test.
If you want to test that a field in a a class changes from false to true, what you really want to do is something like (I don't have your actual constructor, I'm just guessing):
SomeDependency dependency = mock(SomeDependency.class);
// Make a REAL ReferenceLettersBean
ReferenceLettersBean bean = new ReferenceLettersBean(dependency);
// now make your test
rf.checkForDuplicates("abcd#emal.com","abd#gmail.com","abcd#gmail.com");
assertEquals(true,rf.getBoolcheck());
This boolean value seems to be an internal state. This is not something you can directly test with unit tests unless you make it public or it is detectable by influencing the behavior of another method.
So, I have implemented my business classes, where I pass in all dependencies via the constructor, so I can mock those out and easily unit test them. This works great so far, but then, at one point, I need to create an object graph out of those objects. For this, I'm using a static factory (I can't use a DI framework, sadly). Example:
public class FooBar {
public FooBar(Foo foo, Bar bar) {
this.foo = foo;
this.bar = bar;
}
}
public class Foo {
public Foo() {}
}
public class Bar {
public Bar(Foo foo) {
this.foo = foo;
}
}
public class GraphFactory {
public static FooBar newFooBar() {
Foo foo = new Foo();
Bar bar = new Bar(foo);
return new FooBar(foo, bar);
}
}
So, I'm not able to really test the GraphFactory (can't mock the dependencies), which is kinda ok (not much work is done here). But what if construction of the graph is more complex, i.e. it involves looking up some properties, doing JNDI lookups and so on?
Should I still not write a unit test for this? Is my class design maybe broken? Isn't the purpose of unit testing to test classes in isolation?
There is nothing wrong with this design and it is fully testable. If we focus on the single responsibilty of the factory -- it is responsible for assembling the object graph -- the tests for this are straight forward:
Set up the factory with its prerequisites.
Invoke the factory method.
Assert that the object was constructed to your requirements: default values are set, etc.
In the example above, foo, bar, and foobar are the result of the test and do not need to be mocked.
If the assembly of the object graph is more complex, and you need additional services to fetch data and check application settings, guess what happens? These dependencies are passed into the factory through its constructor. You should mock these dependencies to isolate the factory from its dependencies' dependencies. Consumers of your factory would receive a fully wired factory through their constructor; or the factory is assembled at application start-up and made available as a singleton, etc.
This is how DI works. It sounds peculiar because now you have to worry how the factory is created (and who created that object,etc, turtles all the way down) and this is a perfectly natural reaction.
That's why we have DI frameworks to assemble complex object graphs. In a well designed DI application, nothing should know how the graph was assembled. Akin to this design, nothing should know about the DI framework.
The only exception to that rule, is... (drum-roll)... a factory object!
Most DI frameworks will inject the DI container into an object if the object being resolved takes a DI in it's constructor. This greatly simplifies the factory's plumbing, and satisfies our design principles: no one knows how to construct our object except our factory and we've encapsulated knowledge of the DI container to key areas of the application that are responsible for object assembly.
Whew. Now, if you're still following along, how does this change our test? It shouldn't, at least not too much: step #1 changes slightly, where you fill the DI container with mock objects, and then construct the factory with the DI container.
As a matter of taste, some like to use auto-mocking DI containers during testing that will automatically generate mock dependencies when an item is requested. This can remove most of the set up pain.
If the newFooBar method had to be more complex, you could refactor out everything except for the creation of the Foo and the Bar into a package-private initialisation method. Then write tests for the initialisation method.
public class GraphFactory {
public static FooBar newFooBar() {
Foo foo = new Foo();
Bar bar = new Bar(foo);
FooBar toReturn = new FooBar(foo, bar);
initialise( toReturn );
return toReturn;
}
static void initialise( FooBar toInitialise ){
// some stuff here that you can test
}
}
You can't mock or stub static method calls but you can write a unit test for the factory without mocks.
But, why do you use static factory methods?. May be better to store the factory in a static variable if you want to access it in a static way.
You should give a look into Dependecy Injection, which will allow you get rid of the factory when used properly. I recommend you this video as an introduction, it helped me a lot:
http://code.google.com/p/google-guice/
It's an introduction to Guice, a library from google, but it will help you understand DI. Then you'll see how to replace all those 'new' with annotations, letting the library do all the work for you. Some people would recommend Sring instead, but i find Guice more friendly for beginners. I just hope this doesn't fire a Guice vs Spring discussion again :D
I have a looked at similar questions on this board, but none of them answer my question. This sound strange, but is it possible to mock out a constructor call on the object you're mocking.
Example:
class RealGuy {
....
public void someMethod(Customer customer) {
Customer customer = new Customer(145);
}
}
class MyUnitTest() {
public Customer customerMock = createMock(Customer.class)
public void test1() {
//i can inject the mock object, but it's still calling the constuctor
realGuyobj.someMethod(customerMock);
//the constructor call for constructor makes database connections, and such.
}
}
How can I expect a constructor call? I can change the Customer constructor call to use newInstance, but im not sure if that will help. I have no control over what the body of the new Customer(145) constructor does.
Is this possible?
you can do so with EasyMock 3.0 and above.
Customer cust = createMockBuilder(Customer.class)
.withConstructor(int.class)
.withArgs(145)
.addMockedMethod("someMethod")
.createMock();
You can't do this with easymock, as it doesn't support mocking constructors. There's a library called powermock which can do that and is the only mocking library, as far as I know, that can stub constructors and static methods in Java.
import static org.powermock.api.easymock.PowerMock.expectNew;
instance = new UsesNewToInstantiateClass();
expectNew(AnyOldClass.class).andReturn(anyClass);
And this is why you want to inject your dependencies (via Guice or similar package) instead of creating them inside your class.
Then you don't HAVE TO mock their construction.
This assumes (a) that this is your code that you can change, and (b) that the objects in question are complex enough that you should inject them. Constructing simple objects inside your class are fine, but then you shouldn't need to mock them.