I am wondering what is the best practice to test factory behavior code. In my case, the factory creates some dependency instances that will be passed to the constructor of the FooBar instance.
public class FooBarFactory {
private Dependency1 dependency1;
private Dependency2Factory factory;
public FooBarFactory(Dependency1 dependency1, Dependency2Factory factory) {
this.dependency1 = dependency1;
this.factory = factory;
}
public FooBar create() {
return new FooBar(dependency1, factory.create(), new Dependency3());
}
}
The dependencies can be created by some other factories or can be created directly by the factory under test.
To test the factory behavior, what I have to do for now is create some protected getters in FooBar to retrieve the dependencies so I can assert the constructor injection and the dependencies were created correctly.
This is where I am unsure. Adding some getters for the purpose of testing bothers me a little since this it breaks encapsulation. I could also use reflection to retrieve the fields value but I usually consider this bad practice since it is easy to break.
Anyone can provide insights into this problem?
One solution is to mock the FooBar class and verify the constructor invocation through which the instance returned by FooBarFactory#create() was created. Using the JMockit mocking API, such a test would look like:
public class FooBarFactoryTest
{
#Injectable Dependency1 dep1;
#Injectable Dependency2 dep2;
#Cascading #Injectable Dependency2Factory dep2Factory;
#Mocked FooBar mockFooBar;
#Tested factory;
#Test
public void createFooBarWithProperDependencies()
{
assertNotNull(factory.create());
new Verifications() {{ new FooBar(dep1, dep2, (Dependency3) withNotNull()); }};
}
}
I suppose the suggestion that comes to mind would be to in turn inject the FooBarFactory's dependencies as well, so that it takes a Dependency1 and Dependency2Factory as either constructor parameters or as values in setter methods.
As a Unit-Test you should test your unit (class) and just this.
The value created by a factory inside your factory should be tested on its unit-test. For example on your situation, it doesn't make sense to test what dependency2Factory return, because in order to FooBar work, Dependency2Factory should work too (in case it isn't configurable), if it is configurable you can provide your own mock and this would be enough.
And Dependency2Factory should be tested on a separated Unit-Test.
You don't test if the method List.get(int index) works every time you use a list in your implementation right?
How about mocking? Mock every dependency required to run the tested piece of code.
There are a few good mock frameworks like mockito.
Related
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 do I create an object in a Guice Test module that is used as a mock in one test, but requires to be real object in another.
eg.
Consider I have a class called ConfigService. This is injected into another class called UserService using constructor injection. During testing, I use a TestModule which has various classes and their mocks.
TestModule.java:
public class TestModule extends AbstractModule{
#Override
public void configure() {
ConfigService configService = Mockito.mock(ConfigService.class);
bind(ConfigService.class).toInstance(configService);
UserService userService = new UserService(configService);
bind(UserService.class).toInstance(userService);
}
}
In UserServiceTest, I create an injector and use the instances from this TestModule.
Injector injector = Guice.createInjector(new TestModule());
userService = injector.getInstance(UserService.class);
configService = injector.getInstance(ConfigService.class);
This works fine, the place where I face a problem now is when I need to test ConfigService.class.
If I want to use the same TestModule for the ConfigServiceTest, how do I now change the mock object of ConfigService I created earlier to an actual one for testing. The vice versa is also a problem -> ie. if I have a real object of ConfigService, how do I stub and mock the responses in UserService.class.
Is there a way to achieve this or should I be creating separate test modules for mocks and real objects? Or am I going about the entire process in a wrong way?
You can do that using spy method.
ConfigService realConfigService = new ConfigService();
ConfigService configService = Mockito.spy(realConfigService);
bind(ConfigService.class).toInstance(configService);
What spy does is, whenever you provide stubbing, it will behave as if the object is mocked. Otherwise, it will call the real method of the object.
Please check this answer for more in-depth theory.
I have gone through some of the blogs in order to understand the basics of how Mockito annotations work.
However I am facing a doubt as to when does one go for manually instantiating the field annotated with #InjectMocks i.e
#InjectMocks
A a = new A();
And when does one rely on MockitoAnnotations.initMocks() functionality to do the same :
#InjectMocks
A a;
Does this depend on the JunitTestRunner that we employ to run the test cases or is it dependent on the Mockito framework version?
It depends if you are using (declaring) the runner or not.
If you use the runner, you don't need to call MockitoAnnotations.initMocks() yourself - the runner calls it for you.
Usually we go for the runner. When you want to use other runners, though (like Spring's), you can call .initMocks() yourself.
Just to be clear, the MockitoAnnotations.initMocks(this) will:
Instantiate the field annotated with #InjectMocks
Create a mock version of every field annotated with #Mock
Inject the #Mocks in the #InjectMocks variable's fields (or call its constructors or use its setters - it depends on what kind of Dependency Injection you use)
Mockito runner, initMocks and rule code samples
The three code samples below should be equivalent.
With runner:
This first snippet uses the runner, making the call to initMocks() unnecessary.
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
#Mock private MyDependency myDependency;
#InjectMocks private MyClass myClass;
#Test
public void myClass_should_get_stuff_from_dependency() {
when(myDependency.getStuff()).thenReturn("stuff!");
assertThat(myClass.getDependencyStuff(), is("stuff!"));
}
}
Without runner + with manual call to .initMocks():
This other does not use the runner, thus the need for the setUp() method calling our initMocks() friend.
// notice there is no runner
public class MyClassTest {
#Mock private MyDependency myDependency;
#InjectMocks private MyClass myClass;
// but now you have to call initMocks() yourself
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void myClass_should_get_stuff_from_dependency() {
when(myDependency.getStuff()).thenReturn("stuff!");
assertThat(myClass.getDependencyStuff(), is("stuff!"));
}
}
Without runner or manual call, using #Rule:
Finally, as pointed out in the comments (thanks #StefanBirkner), since version 1.10.17, there is also the possibility of using a JUnit #Rule called MockitoRule:
public class MyClassTest {
#Rule
public MockitoRule rule = MockitoJUnit.rule();
#Mock private MyDependency myDependency;
#InjectMocks private MyClass myClass;
#Test
public void myClass_should_get_stuff_from_dependency() {
when(myDependency.getStuff()).thenReturn("stuff!");
assertThat(myClass.getDependencyStuff(), is("stuff!"));
}
}
In general, the decision to instantiate an object which is annotated with #InjectMocks or not is a code style choice. In the majority of cases there will be no difference as Mockito is designed to handle both situations.
However, there is some differences which I have outlined below.
#InjectMocks decouples a test from changes to the constructor.
In the same way using a Dependency Injection framework decouples your production code from changes to the constructor. Allowing Mockito to instantiate an instance of the class for you decouples your test code from changes to the constructor. This means any future changes to the class constructor can be done without causing compilation errors in the unit test.
In my opinion this is the biggest difference and the biggest advantage of #InjectMocks.
Mockito will always call the "biggest" constructor
Note: This difference is only relevant when the code you are working with does not follow best practices.
When there is multiple constructors in a class, Mocktio will call the constructor with the most parameters, the "biggest" constructor.
This only has an impact when,
A "small" constructor contains logic.
This logic is required for the class to function correctly.
The "biggest" constructor does not invoke the next "smallest" constructor.
This is considered bad practice because,
Placing logic within a constructor should be avoided whenever possible.
When there is multiple constructors within a class each constructor should first invoke the constructor before it.
Thanks for your valuable thoughts.
But still it doesn't answer the question as to why one goes for manually instantiating the field annotated with #InjectMocks when the instantiation should be handled by a call to MockitoAnnotations.initMocks().
I get the following error when trying to run the test file :
Caused by: org.mockito.exceptions.base.MockitoException: Field 'student' annotated with #InjectMocks is null.
Please make sure the instance is created before MockitoAnnotations.initMocks();
Example of correct usage:
class SomeTest {
#InjectMocks private Foo foo = new Foo();
#Before public void setUp() {
MockitoAnnotations.initMock(this);
I searched further and found out that the error is thrown if one is using an older version of Mockito framework.
http://myshittycode.com/category/testing/mockito/
Here's how we are using Guice in a new application:
public class ObjectFactory {
private static final ObjectFactory instance = new ObjectFactory();
private final Injector injector;
private ObjectFactory() throws RuntimeException {
this.injector = Guice.createInjector(new Module1());
}
public static final ObjectFactory getInstance() {
return instance;
}
public TaskExecutor getTaskExecutor() {
return injector.getInstance(TaskExecutor.class);
}
}
Module1 defines how the TaskExecutor needs to be constructed.
In the code we use ObjectFactory.getInstance().getTaskExecutor() to obtain and the instance of TaskExecutor.
In unit tests we want to be able to replace this with a FakeTaskExecutor essentially we want to get an instance of FakeTaskExecutor when ObjectFactory.getInstance().getTaskExecutor() is called.
I was thinking of implementing a FakeModule which would be used by the injector instead of the Module1.
In Spring, we would just use the #Autowired annotation and then define separate beans for Test and Production code and run our tests with the Spring4JunitRunner; we're trying to do something similar with Guice.
Okay, first things first: You don't appear to be using Guice the way it is intended. Generally speaking, you want to use Guice.createInjector() to start up your entire application, and let it create all the constructor arguments for you without ever calling new.
A typical use case might be something like this:
public class Foo {
private final TaskExecutor executor;
#Inject
public Foo(TaskExecutor executor) {
this.executor = executor;
}
}
This works because the instances of Foo are themselves injected, all the way up the Object Graph. See: Getting started
With dependency injection, objects accept dependencies in their constructors. To construct an object, you first build its dependencies. But to build each dependency, you need its dependencies, and so on. So when you build an object, you really need to build an object graph.
Building object graphs by hand is labour intensive, error prone, and makes testing difficult. Instead, Guice can build the object graph for you. But first, Guice needs to be configured to build the graph exactly as you want it.
So, typically, you don't create a Singleton pattern and put the injector into it, because you should rarely call Guice.createInstance outside of your main class; let the injector do all the work for you.
All that being said, to solve the problem you're actually asking about, you want to use Jukito.
The combined power of JUnit, Guice and Mockito. Plus it sounds like a cool martial art.
Let's go back to the use case I've described above. In Jukito, you would write FooTest like this:
#RunWith(JukitoRunner.class)
public class FooTest {
public static class Module extends JukitoModule {
#Override
protected void configureTest() {
bindMock(TaskExecutor.class).in(TestSingleton.class);
}
}
#Test
public void testSomething(Foo foo, TaskExecutor executor) {
foo.doSomething();
verify(executor, times(2)).someMethod(eq("Hello World"));
}
}
This will verify that your Mock object, generated by Mockito via Jukito has had the method someMethod called on it exactly two times with the String "Hello World" both times.
This is why you don't want to be generating objects with ObjectFactory in the way you describe; Jukito creates the Injector for you in its unit tests, and it would be very difficult to inject a Mock instead and you'd have to write a lot of boilerplate.
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.