Junit: Calling private method without instance - java

There are no Junits are written in application. But in other module we have started writing Junits using Jmockit. So any core java or Jmockit solution will be highly appreciated.
I have application initialization class, which is singleton, it initialize application by calling database[data load], property file etc. Its object creation is complex.
I am writing new method to initialize class [method name addMoreInitilization].
I want to write Junit for above scenario. Is there way to write Junit for addMoreInitilization method without calling complex object creation logic because it have lot of dependencies and mocking them all is not feasible and also do not want to make method static ?
Pseudo java code for ApplicationStartUp class below
Class ApplicationStartUp {
private ApplicationStartUp applicationStartUp;
// assume single ton implemented
private ApplicationStartUp () {
// complex object creation
addMoreInitilization();
}
public static getInstance() {
}
// new method
private addMoreInitilization() {
// my logic needs to be tested using junit
}
}

You can extend the "ApplicationStartUp" in your tests. Then override the unwanted methods. This way, you can create an Object of the subclass and call the method "addMoreInitialization" of the super class.

Related

how to mock a private method under a injectmocks annotated class in java

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.

Can an instance of a class be created for testing without calling the constructor?

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);
...

How to mock a final class with mockito

I have a final class, something like this:
public final class RainOnTrees{
public void startRain(){
// some code here
}
}
I am using this class in some other class like this:
public class Seasons{
RainOnTrees rain = new RainOnTrees();
public void findSeasonAndRain(){
rain.startRain();
}
}
and in my JUnit test class for Seasons.java I want to mock the RainOnTrees class. How can I do this with Mockito?
Mocking final/static classes/methods is possible with Mockito v2 only.
add this in your gradle file:
testImplementation 'org.mockito:mockito-inline:2.13.0'
This is not possible with Mockito v1, from the Mockito FAQ:
What are the limitations of Mockito
Needs java 1.5+
Cannot mock final classes
...
Mockito 2 now supports final classes and methods!
But for now that's an "incubating" feature. It requires some steps to activate it which are described in What's New in Mockito 2:
Mocking of final classes and methods is an incubating, opt-in feature. It uses a combination of Java agent instrumentation and subclassing in order to enable mockability of these types. As this works differently to our current mechanism and this one has different limitations and as we want to gather experience and user feedback, this feature had to be explicitly activated to be available ; it can be done via the mockito extension mechanism by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line:
mock-maker-inline
After you created this file, Mockito will automatically use this new engine and one can do :
final class FinalClass {
final String finalMethod() { return "something"; }
}
FinalClass concrete = new FinalClass();
FinalClass mock = mock(FinalClass.class);
given(mock.finalMethod()).willReturn("not anymore");
assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());
In subsequent milestones, the team will bring a programmatic way of using this feature. We will identify and provide support for all unmockable scenarios. Stay tuned and please let us know what you think of this feature!
add this in your build file:
if using gradle: build.gradle
testImplementation 'org.mockito:mockito-inline:2.13.0'
if using maven: pom.xml
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>2.13.0</version>
<scope>test</scope>
</dependency>
this is a configuration to make mockito work with final classes
If you faced the Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)
Add the Byte Buddy dependency to your build.gradle file:
testImplementation 'net.bytebuddy:byte-buddy-agent:1.10.19'
src: https://mvnrepository.com/artifact/net.bytebuddy/byte-buddy
You cannot mock a final class with Mockito, as you can't do it by yourself.
What I do, is to create a non-final class to wrap the final class and use as delegate. An example of this is TwitterFactory class, and this is my mockable class:
public class TwitterFactory {
private final twitter4j.TwitterFactory factory;
public TwitterFactory() {
factory = new twitter4j.TwitterFactory();
}
public Twitter getInstance(User user) {
return factory.getInstance(accessToken(user));
}
private AccessToken accessToken(User user) {
return new AccessToken(user.getAccessToken(), user.getAccessTokenSecret());
}
public Twitter getInstance() {
return factory.getInstance();
}
}
The disadvantage is that there is a lot of boilerplate code; the advantage is that you can add some methods that may relate to your application business (like the getInstance that is taking a user instead of an accessToken, in the above case).
In your case I would create a non-final RainOnTrees class that delegate to the final class. Or, if you can make it non-final, it would be better.
In Mockito 3 and more I have the same problem and fixed it as from this link
Mock Final Classes and Methods with Mockito
as follow
Before Mockito can be used for mocking final classes and methods, it needs to be > configured.
We need to add a text file to the project's src/test/resources/mockito-extensions directory named org.mockito.plugins.MockMaker and add a single line of text:
mock-maker-inline
Mockito checks the extensions directory for configuration files when it is loaded. This file enables the mocking of final methods and classes.
Use Powermock. This link shows, how to do it: https://github.com/jayway/powermock/wiki/MockFinal
Just to follow up. Please add this line to your gradle file:
testCompile group: 'org.mockito', name: 'mockito-inline', version: '2.8.9'
I have tried various version of mockito-core and mockito-all. Neither of them work.
I had the same problem. Since the class I was trying to mock was a simple class, I simply created an instance of it and returned that.
I guess you made it final because you want to prevent other classes from extending RainOnTrees. As Effective Java suggests (item 15), there's another way to keep a class close for extension without making it final:
Remove the final keyword;
Make its constructor private. No class will be able to extend it because it won't be able to call the super constructor;
Create a static factory method to instantiate your class.
// No more final keyword here.
public class RainOnTrees {
public static RainOnTrees newInstance() {
return new RainOnTrees();
}
private RainOnTrees() {
// Private constructor.
}
public void startRain() {
// some code here
}
}
By using this strategy, you'll be able to use Mockito and keep your class closed for extension with little boilerplate code.
Another workaround, which may apply in some cases, is to create an interface that is implemented by that final class, change the code to use the interface instead of the concrete class and then mock the interface. This lets you separate the contract (interface) from the implementation (final class). Of course, if what you want is really to bind to the final class, this will not apply.
Time saver for people who are facing the same issue (Mockito + Final Class) on Android + Kotlin. As in Kotlin classes are final by default. I found a solution in one of Google Android samples with Architecture component. Solution picked from here : https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample
Create following annotations :
/**
* This annotation allows us to open some classes for mocking purposes while they are final in
* release builds.
*/
#Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class OpenClass
/**
* Annotate a class with [OpenForTesting] if you want it to be extendable in debug builds.
*/
#OpenClass
#Target(AnnotationTarget.CLASS)
annotation class OpenForTesting
Modify your gradle file. Take example from here : https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/build.gradle
apply plugin: 'kotlin-allopen'
allOpen {
// allows mocking for classes w/o directly opening them for release builds
annotation 'com.android.example.github.testing.OpenClass'
}
Now you can annotate any class to make it open for testing :
#OpenForTesting
class RepoRepository
Actually there is one way, which I use for spying. It would work for you only if two preconditions are satisfied:
You use some kind of DI to inject an instance of final class
Final class implements an interface
Please recall Item 16 from Effective Java. You may create a wrapper (not final) and forward all call to the instance of final class:
public final class RainOnTrees implement IRainOnTrees {
#Override public void startRain() { // some code here }
}
public class RainOnTreesWrapper implement IRainOnTrees {
private IRainOnTrees delegate;
public RainOnTreesWrapper(IRainOnTrees delegate) {this.delegate = delegate;}
#Override public void startRain() { delegate.startRain(); }
}
Now not only can you mock your final class but also spy on it:
public class Seasons{
RainOnTrees rain;
public Seasons(IRainOnTrees rain) { this.rain = rain; };
public void findSeasonAndRain(){
rain.startRain();
}
}
IRainOnTrees rain = spy(new RainOnTreesWrapper(new RainOnTrees()) // or mock(IRainOnTrees.class)
doNothing().when(rain).startRain();
new Seasons(rain).findSeasonAndRain();
Give this a try:
Mockito.mock(SomeMockableType.class,AdditionalAnswers.delegatesTo(someInstanceThatIsNotMockableOrSpyable));
It worked for me. "SomeMockableType.class" is the parent class of what you want to mock or spy, and someInstanceThatIsNotMockableOrSpyable is the actual class that you want to mock or spy.
For more details have a look here
This can be done if you are using Mockito2, with the new incubating feature which supports mocking of final classes & methods.
Key points to note:
1. Create a simple file with the name “org.mockito.plugins.MockMaker” and place it in a folder named “mockito-extensions”. This folder should be made available on the classpath.
2. The content of the file created above should be a single line as given below:
mock-maker-inline
The above two steps are required in order to activate the mockito extension mechanism and use this opt-in feature.
Sample classes are as follows:-
FinalClass.java
public final class FinalClass {
public final String hello(){
System.out.println("Final class says Hello!!!");
return "0";
}
}
Foo.java
public class Foo {
public String executeFinal(FinalClass finalClass){
return finalClass.hello();
}
}
FooTest.java
public class FooTest {
#Test
public void testFinalClass(){
// Instantiate the class under test.
Foo foo = new Foo();
// Instantiate the external dependency
FinalClass realFinalClass = new FinalClass();
// Create mock object for the final class.
FinalClass mockedFinalClass = mock(FinalClass.class);
// Provide stub for mocked object.
when(mockedFinalClass.hello()).thenReturn("1");
// assert
assertEquals("0", foo.executeFinal(realFinalClass));
assertEquals("1", foo.executeFinal(mockedFinalClass));
}
}
Hope it helps.
Complete article present here mocking-the-unmockable.
Yes same problem here, we cannot mock a final class with Mockito. To be accurate, Mockito cannot mock/spy following:
final classes
anonymous classes
primitive types
But using a wrapper class seems to me a big price to pay, so get PowerMockito instead.
I think you need think more in principle. Instead you final class use his interface and mock interface instead.
For this:
public class RainOnTrees{
fun startRain():Observable<Boolean>{
// some code here
}
}
add
interface iRainOnTrees{
public void startRain():Observable<Boolean>
}
and mock you interface:
#Before
fun setUp() {
rainService= Mockito.mock(iRainOnTrees::class.java)
`when`(rainService.startRain()).thenReturn(
just(true).delay(3, TimeUnit.SECONDS)
)
}
Please look at JMockit. It has extensive documentation with a lot of examples. Here you have an example solution of your problem (to simplify I've added constructor to Seasons to inject mocked RainOnTrees instance):
package jmockitexample;
import mockit.Mocked;
import mockit.Verifications;
import mockit.integration.junit4.JMockit;
import org.junit.Test;
import org.junit.runner.RunWith;
#RunWith(JMockit.class)
public class SeasonsTest {
#Test
public void shouldStartRain(#Mocked final RainOnTrees rain) {
Seasons seasons = new Seasons(rain);
seasons.findSeasonAndRain();
new Verifications() {{
rain.startRain();
}};
}
public final class RainOnTrees {
public void startRain() {
// some code here
}
}
public class Seasons {
private final RainOnTrees rain;
public Seasons(RainOnTrees rain) {
this.rain = rain;
}
public void findSeasonAndRain() {
rain.startRain();
}
}
}
Solutions provided by RC and Luigi R. Viggiano together is possibly the best idea.
Although Mockito cannot, by design, mock final classes, the delegation approach is possible. This has its advantages:
You are not forced to change your class to non-final if that is what your API intends in the first place (final classes have their benefits).
You are testing the possibility of a decoration around your API.
In your test case, you deliberately forward the calls to the system under test. Hence, by design, your decoration does not do anything.
Hence you test can also demonstrate that the user can only decorate the API instead of extending it.
On a more subjective note:
I prefer keeping the frameworks to a minimum, which is why JUnit and Mockito are usually sufficient for me. In fact, restricting this way sometimes forces me to refactor for good as well.
If you trying to run unit-test under the test folder, the top solution is fine. Just follow it adding an extension.
But if you want to run it with android related class like context or activity which is under androidtest folder, the answer is for you.
Add these dependencies for run mockito successfully :
testImplementation 'org.mockito:mockito-core:2.24.5'
testImplementation "org.mockito:mockito-inline:2.24.5"
Mocking final classes is not supported for mockito-android as per this GitHub issue. You should use Mockk instead for this.
For both unit test and ui test, you can use Mockk with no problem.
If you need to use Mockito in an instrumented test in Android (i. e. running in an Android device), you cannot use mockito-inline. There is a special mockito-android version which doesn't solve the "final class" problem either. The only solution which seems to work is the Dexmaker library. The only limitation is that it works only in Android P (Android 9, API 28) and higher. It can be imported as follows:
androidTestImplementation "com.linkedin.dexmaker:dexmaker-mockito-inline:2.28.1"
Beware that there is also a "dexmaker-mockito" version which doesn't work for final classes either. Make sure you import "dexmaker-mockito-inline".
As others have stated, this won't work out of the box with Mockito. I would suggest using reflection to set the specific fields on the object that is being used by the code under test. If you find yourself doing this a lot, you can wrap this functionality in a library.
As an aside, if you are the one marking classes final, stop doing that. I ran across this question because I am working with an API where everything was marked final to prevent my legitimate need for extension (mocking), and I wish that the developer had not assumed that I would never need to extend the class.
For us, it was because we excluded mockito-inline from koin-test. One gradle module actually needed this and for reason only failed on release builds (debug builds in the IDE worked) :-P
For final class add below to mock and call static or non static.
1- add this in class level
#SuppressStatucInitializationFor(value ={class name with package})
2- PowerMockito.mockStatic(classname.class) will mock class
3- then use your when statement to return mock object when calling method of this class.
Enjoy
I was able to overcome this message:
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class org.slf4j.impl.Log4jLoggerAdapter
Mockito cannot mock/spy because :
final or anonymous class
from this: log = spy(log);
By using this instead:
log = mock(Logger.class);
Then it works.
I guess that "default" logger adapter is an instance of a final class so I couldn't "spy" it, but I could mock the whole thing. Go figure...
This may mean that you could substitute it for some other "non final" instance if you have that handy, as well. Or a simplified version, etc. FWIW...
I am writing the steps I followed after various unsuccessful attempts to mock final/private classes and their methods in Java 11, which finally worked for me.
Create a file named org.mockito.plugins.MockMaker inside
your test/resources/mockito-extensions folder. Please create
mockito-extensions folder if not present already.
Add a single line mock-maker-inline as the content of the above org.mockito.plugins.MockMaker file
Add
#RunWith(PowerMockRunner.class)
#PowerMockIgnore({"javax.management.*", "jdk.internal.reflect.*", "com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "org.w3c.*"})
#PrepareForTest(Utility.class)
annotations at the class level.
Setup process in the test class
#Before
public void setup () {
MockitoAnnotations.initMocks(this);
Mockito.mockStatic(ClassToBeMocked.class);
}
Use Mockito.when(..).thenReturn(..) for assertions
In case of multiple test cases, add the below code
#After
public void after() {
Mockito.framework().clearInlineMocks();
}
The mockito version which I am using: 3.9.0
Java version: 11
Didn't try final, but for private, using reflection remove the modifier worked ! have checked further, it doesn't work for final.

Best Practice: Testing Interface Contract Compliance?

Assume that interface for is defined
interface Foo {
int getBaz();
void doBar();
}
Further assume that the contract states that everytime doBar is called baz is incremented. (Ok this is a contrived bit of code but stick with me here)
Now I want to provide a unit test that I can provide to Foo implementers so that they can verify that they meet all the contract conditions.
class FooTest {
protected Foo fooImpl;
#Test
public void int testBazIncrement()
{
int b = fooImpl getBaz();
fooImpl.doBar();
Assert.assertEquals( b+1, fooImpl.getBaz();
}
}
What are the best practices for making the test available to the implemnters of Foo? It seems to me that there needs to be a mechanism for them to call the FooTest and provide a Foo or a FooFactory to construct Foo instances. Furthermore, if there are many tests (think big interface) then I want to put all those tests in one FooTest class.
Are there any best practices for how to implement such tests?
This is a textbook example of Dependency Injection. If you use Spring as the DI container, you can wire in the fooImpl
#Inject
protected Foo fooImpl;
Your test needs to be annotated with #RunWith(SpringJUnit4ClassRunner.class), and it's up to the interface provider to configure Spring with their implementation.
Without a DI container, you can just create an abstract test class with all the tests in it and an abstract method to provide the implementation object.
protected abstract Foo createFoo();
It's up to the implementation provider to subclass the test and implement the abstract method.
class FooImplTest extends FooTestSuper {
#Override
protected Foo createFoo() {
return new FooImpl();
}
If you have multiple tests, consider JUnit's #Suite annotation. It's compatible with the Spring test runner.
You can implement a testDataFactory where you istance your objects, or use GSon for create your objects (personally, I like GSon, is clear and fast, you learn it in a few time).
For the test implementation, I suggest to write more tests and not a single one.
In this way, unit test can be indipendent and you can segregate your problems in a closed structure.
Sonar
Sonar is a tool that help you a lot, making analisys of your code. You can see from sonar front-end how you application is tested:
sonar unit test
as you can see, Sonar can show you where your code is tested or not
Why not just have, say, a InterfaceTester that gets called from the unit tests InterfaceImplATest, InterfaceImplBTest, etc?
e.g.
#Test
public void testSerialisation()
{
MyObject a = new MyObject();
...
serialisationTester.testSimpleRoundTrip(a);
serialisationTester.testEdgeCases(a);
...
}
After much pondering and some dead-ends I have begun using the following pattern:
In the following:
[INTERFACE] refers to the interface being tested.
[CLASS] refers to the implementation of the interface being tested.
Interface tests are built so that developers may test that implementations meet the contract
set out in the interface and accompanying documentation.
The major items under test use an instance of an [INTERFACE]ProducerInterface to create the instance of the object being tested. An implementation of [INTERFACE]ProducerInterface must track all the instances created during the test and close all of them when requested. There is an Abstract[INTERFACE]Producer that handles most of that functionality but requires a createNewINTERFACE implementation.
TESTS
Interface tests are noted as Abstract[INTERFACE]Test. Tests generally extend the Abstract[INTERFACE]ProducerUser class. This class handles cleaning up all the graphs at the end of the tests and provides a hook for implementers to plug in their [INTERFACE]ProducerInterface implementation.
In general to implement a test requires a few lines of code as is noted in the example below
where the new Foo graph implementation is being tested.
public class FooGraphTest extends AbstractGraphTest {
// the graph producer to use while running
GraphProducerInterface graphProducer = new FooGraphTest.GraphProducer();
#Override
protected GraphProducerInterface getGraphProducer() {
return graphProducer;
}
// the implementation of the graph producer.
public static class GraphProducer extends AbstractGraphProducer {
#Override
protected Graph createNewGraph() {
return new FooGraph();
}
}
}
SUITES
Test suites are named as Abstract[INTERFACE]Suite. Suites contain several tests that excersize all of the tests for components of the object under test. For example if the Foo.getBar() returned an instance of the Bar interface the Foo suite includes tests for the Foo iteself as well as running the Bar tests the Bar. Running the suites is a bit more complicated then running the tests.
Suites are created using the JUnit 4 #RunWith(Suite.class) and #Suite.SuiteClasses({ })
annotations. This has several effects that the developer should know about:
The suite class does not get instantiated during the run.
The test class names must be known at coding time (not run time) as they are listed in the annotation.
Configuration of the tests has to occur during the static initialization phase of class loading.
To meet these requirements the Abstract[INTERFACE]Suite has a static variable that holds the instance of the [INTERFACE]ProducerInterface and a number of local static implementations of the Abstract tests that implement the "get[INTERFACE]Producer()" method by returning the static instance. The names of the local tests are then used in the #Suite.SuiteClasses annotation. This makes creating an instance of the Abstract[INTERFACE]Suite for an [INTERFACE] implementation fairly simple as is noted below.
public class FooGraphSuite extends AbstractGraphSuite {
#BeforeClass
public static void beforeClass() {
setGraphProducer(new GraphProducer());
}
public static class GraphProducer extends AbstractGraphProducer {
#Override
protected Graph createNewGraph() {
return new FooGraph();
}
}
}
Note that the beforeClass() method is annotated with #BeforeClass. the #BeforeClass causes it to be run once before any of the test methods in the class. This will set the static
instance of the graph producer before the suite is run so that it is provided to the enclosed tests.
FUTURE
I expect that further simplification and removal duplicate code can be achieved through the use of java generics, but I have not gotten to that point yet.
Here are some of my thoughts about how to make a qualified unit test:
First of all, try to make your a implementer class fully tested, which means all of its methods should be covered by the UT. Doing this will save you a lot of time when you need to refactor your code. For your case, it could be :
class FooTest {
protected Foo fooImpl;
#Test
public void testGetBaz() {
...
}
#Test
public void testDoBar() {
...
}
}
You will find you need to check the internal state of your class and there is nothing wrong it for UT should be a kind of white-box test.
Second, all methods should be tested separately and not depend on each other. In my opinion, for your code posted above, it looks like more than a function test or an integration test, but it's also necessary.
Third, I don't think it's a good practice to use spring or other container to assemble the target object for you, which will make your test running relatively slow, especially when there a load of tests to run. And your class should intrinsically be pojo and you can complete the assembling in another method in your test class if your target object is really complex.
Fourth, if the parent interface of some class is really big, Dividing the test methods into several groups is something you should do. Here is more info.

EasyMock: Mock out a constructor call in java

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.

Categories

Resources