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.
Related
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);
...
Is there anyway in Mockito/PowerMockito to mock some methods of super class.
Below is a scenario, it does a multilevel inheritance.
public class Network {
public String getNetwork() {
return "Technology";
}
}
Here is another class Technology that extends Network
public class Technology extends Network {
public Type getTechnology() {
String network = getNetwork();
if(network == null){
return null;
}
return network;
}
}
Another class Service that extends Technology
public class BaseService extends Technology {
public void getServices() {
Type type = getTechnology();
if(type == null){
throw new Exception('Type not found');
}
}
}
I want to write a test case for BaseService class method getServices, so that it should throw an exception when the technology class Type is null.
I have tried with a few steps but couldn't help.
Sample test case written
#Test
public void test_get_services_should_throw__exception_when_type_is_null() throws Exception{
//Arrange
expectedException.expect(Exception.class);
baseService = Mockito.mock(BaseService.class, Mockito.CALLS_REAL_METHODS);
when(baseService.getTechnology()).thenReturn(null);
//Act
baseService.getServices();
}
The code snippet above is just a sample and may contain errors. Please ignore if any.
Please help me to resolve this issue.
Thanks in advance.
This should work.
#RunWith(MockitoJUnitRunner.class)
public class TestInheritance {
#Spy
BaseService baseService;
#Rule
public final ExpectedException expectedException = ExpectedException.none();
#Test
public void test_get_services_should_throw__exception_when_type_is_null() throws Exception{
expectedException.expect(Exception.class);
when(baseService.getTechnology()).thenReturn(null);
baseService.getServices();
}
}
Use the spy object. Here baseService would be a spy.
You can add behaviors on the spy object as you do with mock'ed ones.
I'll give you a little headstart-
baseService = Mockito.spy(new BaseService());
BTW you won't see this problem if you favor composition over inheritance.
As other's have already written, you could do this with a spy, but I'd suggest a different approach to your testing instead.
In your very simple example, all the null-checks are irrelevant as you're always returning a constant, non-empty value. In that particular case there is no point in mocking at all.
But given that your base class may actually have different return values. Instead of mocking the parent's method, you should write your test in that way, that you trigger the alternative paths by alter the "state" (class state or global state like the environment) preconditions of your class.
By this you create an actual situation where the parent behaves different.
This would create a test setup that is much more robust to changes (due to refactoring) and further provide a first form of integration testing, as you're testing whether your specialized class integrates
with the parent class.
Aiming for strictly isolated unit tests may lead to test suites that don't cover collaboration between classes properly. Strictly isolated tests may form the foundation of your automation testing approach, but you should have tests with some degree of integration on top of that (not referring to "real" integration tests here, where you integrate with external services).
My advise here, use mocks only on well defined boundaries (interfaces) and use the real classes as much as possible, and design your tests accordingly (not train the mocks, prepare the preconditions instead).
Had a quick look at past questions, couldn't see something similar so here goes:
I also made a mistake in choosing dummy names for this example to illustrate my point, I'll rename them.
I have a class which has a JUnit test:
public class CheckFilter {
#Test
public void Run_filter_test() {
//some code
}
}
And then another class:
public class CheckVideoPlays {
#Test
public void Play_video_in_full() {
//some more code here etc
}
}
Finally, how do I call these two tests from another class, obviously you can't extend multiple classes.
public class RunAllTests {
//How do i call both
//eg
//
//Run_filter_test();
//Play_video_in_full();
}
Note: I don't want to call the class. Don't want to run as:
#RunWith(Suite.class)
#Suite.SuiteClasses({
CheckFilter.class,
CheckVideoPlays.class
})
A few things.
Change the name of Sanatize_all_inputs to the (java standard form) camel case, perhaps sanitizeAllImports. When using Java, obey Java.
It seems likely that you will sanitize inputs once per test,
which, to me, indicates that you want a class level variable of type ConvertAll in your jUnit test class.
Either use composition (another class level variable of type BaseTestBlammy) or inheritance (extend class BaseTestBlammy) to acquire access to the BaseTestBlammy methods.
Here is an example:
public MyJunitTestKapow
extends BaseTestBlammy
{
private final ConvertAll convertAll;
public MyJunitTestKapow()
{
convertAll = new ConvertAll();
}
#Test
public void someTest()
{
convertAll.sanitizeAllInputs(...);
... // do the rest of the test here.
}
}
You could make static method in ConvertAll.sanitize then call this method in both ConvertAll.Sanitise_all_inputs test and CheckFilter.Run_filter_test
As better (more maintainable and powerful) solution you may create Sanitiser class with sanitise() method (method may be static or not). Then each class that requires sanitise functionality will call Sanitiser.sanitise. This soltion may be better in long run- you may pass paramethers to sanitise method (or to Sanitiser constructor), Sanitiser may have some internal state, etc
Side note: you may consider migrating to Junit5 (basically it is just change of imported packages). Junit5 has #DisplayName annotation that declares nice test method names (with spaces). So your test methods will respect Java naming convention.
#Test
#DiplayName("Sanitize all inputs")
public void sanitiseAllInputs() {
//some more code here etc
}
I am writing a tool (not for Testing purpose) based on some existing code (class A, module B here) which I can't touch, I want to mock their behaviours.
I am trying to find something like Mockito for my java application but not under JUnit/Testing environment, or a solution which can make Mockito work out of JUnit/Testing environment.
Here is class A:
public final class A{ // I can't touch this class, and I can't touch module B where A is called
public static String getType(String name){
... // DataBase access
}
}
Here is my application:
public class myApp{
public Object compute(String name){
// execute module B's code, where A is widely called
return computedObject;
}
}
I don't want to access database ihn my aplication, I just want to mock A's method in my java application like Mockito does in JUnit, but I am not able to make it work out of JUnit or find similar framework for java application.
If I use Mockito, then I will have
#RunWith(PowerMockRunner.class)
#PrepareForTest(A.class) // does this mean Mockito only works under Testing environment?
public class myApp{
#Test
public Object compute(String name){
// mock A
// call code in module B
return computedObject;
}
}
but I can not call a test method and get its return value from my java application which is not JUnit, JUnitCore can only execute all tests and can't return the value of some Test method.
I need do exactly the same thing as Mockito but not under Testing
environment, I can't modify the class A neither the module B, and in
the future I may need to mock the creation of object/mock static
method... (same functionality as Mockito), but I don't want to rewrite
a Mockito for java application since it will be too costly, so a
similar framework working out of JUnit would be great.
Could anyone give me any idea?
EDIT :
I think my use case is quite common, and such a framework would be quite helpful in some cases. Why there isn't such framework, did I miss something or I made some mistake?
If it is not an option to modify your "module B" (as described in the comments of your question) you could use a byte code instrumentation library like ByteBuddy, Javassist or CGLIB. These libraries allow you to rewrite the byte code of your methods at runtime and are typically used in java agents.
(Btw, Mockito does exactly that. It uses ByteBuddy to instrument your classes)
If you write the tool
"I am writing a tool which has a dependency on module B"
then you can remove the dependency to B by using an Interface:
public interface IData {
String getType(String a)
}
and within B:
public class BDataAcess implements IData {
public String getData(String a) {
return A.getType();
}
}
and use it in productive code this way
IDataAcess dataAcess = new BDataAcess();
dataAcess.getData("money");
in unit test you replace the dataAcess with your own IDataAcess.
application.setDataAcess(new MyTestDataAcess());
where MyTestDataAcess is implemented in your unit test folder.
You don't need any special lib for that, just pure java.
I have been setting up some contract JUnit 4 tests (following advice in answer to this question) - e.g. if I have an interface (I've included generics in the example, since I'm using them in my project) - but, this is a significantly simplified example:
public interface MyInterface<T> {
public T myMethod();
}
I can create an abstract contract test - e.g.:
public abstract class AbstractMyInterfaceTest<T> {
private final MyInterface<T> _impl;
// plus, store stuff to test against;
public AbstractMyInterfaceTest(MyInterface<T> impl, ... stuff to test against){
_impl = impl;
// stuff to test against...
}
#Test
public void testMyMethod(){
// test some stuff...
}
}
...and extend this abstract test class for each implementation (which I am running with #RunWith(Parameterized.class)). I'm also passing some variables to test the implementation of the interface against into the abstract test class.
However, in actuality, some interfaces return objects that are implementations of other interfaces, and I would like to be able to test this implementation using the abstract contract class for that interface (...and against the relevant variables). For example, a method in MyInterface might return an Iterator - which is an interface. I have a separate AbstractIteratorTest, which runs a contract test for Iterator against a set of values, and I want to check that the Iterator returned by the implementations of MyInterface passes the contract tests in AbstractIteratorTest with the expected set of values.
At the moment, I'm adding the following to the abstract test classes:
// N.b. not setting #Test - so doesn't run all tests twice...
public void runTests(){
testMyMethod();
// etc.
}
However, this doesn't run each test independently (e.g. running setUp() before each test method), so there are problems if those contract tests expect the implementation to be in a particular state for each test. (A specific example would be testing implementations of the Iterator interface, where each test method can change the state of the tested Iterator)
Is there was a better way of doing this, perhaps making use of features in JUnit 4?
I've seen stuff about the #RunWith(Suite.class) annotation, but that seems to be about running multiple test classes from a single test class, and doesn't allow you to pass variables into the different test classes that are being run. There may be a way to use this Suite to solve my problem, but I'm not sure what it is...
Firstly, if you're subclassing your abstract test class, you don't need to use Parameterized. You could use Parameterized instead of subclassing, but you're unlikely to need both. Unless you want to test multiple instances of each implementation, which i will demonstrate below!
One way to do this would be to make the tests for returned instances simply be more subclasses or parameterisations of AbstractAnotherInterfaceTest.
Say you have:
public abstract class AbstractAnotherInterfaceTest {
private AnotherInterface instance;
protected AbstractAnotherInterfaceTest(AnotherInterface instance) {
this.instance = instance;
}
#Test
public void everythingIsOkay() {...}
}
And you had:
public class Pony implements AnotherInterface { ... }
public class PonyProducingMyInterface implements MyInterface<Pony> { ... }
You could write:
#RunWith(Parameterized.class)
public class PonyTest extends AbstractAnotherInterfaceTest {
#Parameterized.Parameters
public static Collection<Pony> ponies() {
return Arrays.asList(
new Pony(), // base case
new PonyProducingMyInterface().myMethod() // testing the factory
);
}
public PonyTest(Pony instance) {
super(pony);
}
}
This is admittedly a bit weird, though, because the new PonyProducingMyInterface().myMethod() case is really a test for PonyProducingMyInterface, but is classified under AbstractAnotherInterfaceTest.
The only approach i can think of that would make use of the AbstractAnotherInterfaceTest tests in some subclass of AbstractMyInterfaceTest would be to write a custom ParentRunner which knew how to set up instances of AbstractAnotherInterfaceTest as children of instances of AbstractMyInterfaceTest. You'd probably want to make that a bit generic, using annotations to guide the process.