I am following an older Java tutorial that is teaching the concept of the Service layer, my program is a very simple program that will create a list of Bills and their due dates. Where I am stuck is in creating the JUnit Test for factory methods.
First here is the Bill Constructor
public Bill(String bname, Double bamount, Date bdate, String bfrequency){
this.billName = bname;
this.billAmount = bamount;
this.billDueDate = bdate;
this.frequency = bfrequency;
}
Next is the Interface to save and get these bills
public interface IBill {
public void save(Bill bill);
public Bill read(Bill readbill);
}
Bear with me, next is the concrete implementation of the interface which are stubbed out for now, nothing implemented yet
public class BillSvcImpl implements IBill {
#Override
public void save(Bill bill) {
System.out.println("Entering the Store BillInfo method");
}
#Override
public Bill read(Bill readbill) {
System.out.println("Entering the Read BillInfo method");
return null;
}
}
Then there is the factory method that will create/call the concrete implementation
public class Factory {
public IBill getBillInfo(){
return new BillSvcImpl();
}
}
Then finally the JUnit test where I am stucked
public class BillSvcTest extends TestCase {
private Factory factory;
#Before
public void setUp() throws Exception {
super.setUp();
factory = new Factory();
}
#test
public void testSaveBill(){
IBill bill = factory.getBillInfo();
Bill nanny = new Bill("Nanny",128d,new Date(6/28/2013),"Montly");
bill.save(nanny);
//what goes here??, Assert??
}
#test
public void testReadBill(){
//How can I write a Test for this??
//Please help
}
}
The instruction is
Create a JUnit Test for your service, The test should use the Factory to get the service, instantiated in the setUp() method.
My service/interface have two methods save and get, how can I create a test for these before I start the actual implementation.
Any help is appreciated.
Thanks
First, don't extend TestCase - instead, use JUnit 4.x.
Second, I take great umbrage against a method with side effects. There's no reason to modify your save method to return a boolean instead of void; you just have to take an alternative approach to testing the method.
Third, I'm of the persuasion that a simple unit test won't be able to cover the save functionality of this method. Something that reads like it would be persisted someplace is better suited for an integration test of some kind (using the database, ensuring that the file exists and the contents are correct, etc).
The main question you want to answer when you're unit testing is, "What is the expected result of this method invocation given this parameter?" When we call save, what do we expect to happen? Do we write to a database? Do we serialize the contents and write to a file? Do we write XML/JSON/plain text out? That would have to be answered first, and then could a useful test be written around it.
The same thing applies for read - what do I expect to receive as input when I attempt to read a bill? What do I gain from passing in a Bill object, and returning a Bill object? (Why would an outside caller have a notion of a bill that I'm trying to read?)
You have to flesh out your expectations for these methods. Here's an approach I use to write unit tests:
Given a specific input,
when I call this method,
then I expect these things to be true.
You have to define your expectations before you can write the unit tests.
IMO save method should return something to say whether Bill got saved or not. I would have kept save method like this
public boolean save(Bill bill) {
System.out.println("Entering the Store BillInfo method");
boolean result = false;
try {
//..... saving logic
result = true;
}
catch(Exception e) {
result = false;
e.printStackTrace();
}
return result;
}
and did an assert in the testcase as
#Test
public void testSaveBill(){
//Success
IBill bill = factory.getBillInfo();
Bill nanny = new Bill("Nanny",128d,new Date(6/28/2013),"Montly");
assertTrue(bill.save(nanny));
//Failure
assertFalse(bill.save(null));
}
Generally, implementation of read() and store() involves integrating with external system such as database, file system. This makes the test go hand in hand with the external system.
#Test
public void insertsBillToDatabase() {
//setup your database
bill.store(aBill);
//fetch the inserted bill then assert
}
These tests are focused on whether you component is making an correct abstration on the external system.
Tests depending on external system are expensive because they are relatively slow and difficult to setup/cleanup. You'd better seperate business conerns and integration concerns if there are some complex business logic in the store().
public void store(Bill bill) {
//business logic
billDao.save(bill); // delegate to an injected dao, you can replace it with a test double in test code
}
#Test
public void doesSthToBillBeforeSave() {
//replace your billDao with a stub or mock
bill.store(aBill);
//assert the billDao stub / mock are correctly invoked
//assert bill's state
}
Related
Today I learned about Mockito and while playing around with it I found something I do not understand.
Say I would like to test the following piece of code:
public void stop(boolean showMessage) {
if(executor != null && !executor.isShutdown() && this.isRunning) {
if(showMessage) {
View.getSingleton().showMessageDialog(Constant.messages.getString("sessionchecker.stopmessage"));
}
executor.shutdownNow();
executor = null;
extension.getCountdownTimer().stopCountdown();
this.isRunning = false;
this.usersReady.clear();
}
}
Since the stop method is a void I would need to call doAnswer (If I understand correctly).
So I tried the following:
#Test
public void testStopIsRunningFalse() {
Mockito.when(controller.isRunning()).thenReturn(true); // Mock a running service
Mockito.doAnswer(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
if(controller.isRunning()) {
// Normally would actually shut down service
Mockito.when(controller.isRunning()).thenReturn(false); // Service should stop
}
return null;
}
}).when(controller).stop(false);
controller.stop(false);
boolean expected = false;
assertEquals(expected, controller.isRunning());
}
I, however, do not understand what the purpose of a test like this would be. Why would I test it like this since this will never fail (the parameter isRunning is being set as I would expect it to be).
Basically I only need to test the state of certain fields (isRunning and executor for example). These fields do not have public getters or setters however..
Therefore, I think I misunderstand the usage of the deAnswer. Could someone help me out?
If I understand your code example, it appears you are mocking the object you want to test, which is a no-no 99.9% of the time. You generally only want to mock direct collaborators of the class you are testing. Collaborators consist of things such as injected services (or other injected fields), and arguments of the method you are testing -- essentially anything that represents initial state of your class under test before you invoke the method being tested.
Suppose I have class with simple dependency:
public interface Dependency {
int doSomething(int value);
void doMore(int value);
int doALotMore(int value);
}
public final class A implements SomeInterface {
private final Dependency dep;
public A (Dependency dep) {
this.dep = dep;
}
#Override
public int add(final int x) {
dep.doMore(x);
return x + dep.doSomething(x) + dep.doALotMore(x);
}
}
And I'm writing test using mocks:
public class TestA {
private Dependency mockDep;
private SomeInterface a;
#Before
public void setUp() {
mockDep = Mockito.mock(Dependency.class);
a = new A(mockDep);
}
#Test
public void shouldAdd() {
final int x = 5;
when(mockDep.doSomething(x)).thenReturn(6);
when(mockDep.doALotMore(x)).thenReturn(7);
int actual = a.add(x);
assertThat(actual, is(18));
verify(mockDep, times(1)).doSomething();
verify(mockDep, times(1)).doALotMore();
verify(mockDep, times(1)).doMore();
verifyNoMoreInteractions(mockDep);
}
}
So far so good.
So the question is: do we violate encapsulation of class A by verifying how exactly the dependency was used? Does it really needed to test that dependency was used in exactly that way? Shouldn't we test A like a black-box (delete verify invocations from test case and leave just assertThat)? And how to deal with dependencies in such case?
The reason I'm asking is that I caught myself writing good amount of verification dependency code and it seems that we start to test actual internal realization details about class. And I feel uncomfortable about that because when I will try to rewrite this realization details in another way I need to rewrite test cases although the result of add for example will be the same. If I would test my class as a black-box I can change realization details and still be sure that given input will give same output.
Or it is necessary to actually test exactly the realization details and that is the point of unit-test itself? It seems somewhat wrong for me.
Consider this test instead:
public class TestA {
private Dependency mockDep;
private SomeInterface a;
private final int x = 5;
#Before
public void setUp() {
mockDep = Mockito.mock(Dependency.class);
a = new A(mockDep);
when(mockDep.doSomething(x)).thenReturn(6);
when(mockDep.doALotMore(x)).thenReturn(7);
}
#Test
public void shouldAdd() {
int actual = a.add(x);
assertThat(actual, is(18));
}
}
It really depends on logic which you're testing. Since your example don't provide any context, I'll give you a case when I feel not only comfortable to test such interaction, but even mandatory:
Let's say you're testing authentication token validation. You pas some token to your validator and it returns true/false. Inside of your validator you're calling some jwt.validate or any other 3rd party hash validation method. In this case I need to know that this validator will be called every time, because I can introduce some if token == null condition inside which will bypass this validation call and just return false. Then your tests could still pass but your code is now vulnerable to timing attack.
It's one kind of example. The other type of test I'm comfortable of testing that way is so called border testing. I want to know that my class triggers stripe payment gateway - so I mock it and just make sure it gets called without checking anything sophisticated in this particular test.
Which are differences between andAnswer() and andDelegateTo() methods in EasyMock in terms of usage?
First difference
I know that when andAnswer method is used, it is skipped the constructor call. This is important if the constructor makes extra things.
class Dummy {
public Dummy(Object someArgument) {
// some validations of arguments
System.out.println("the constructor is called");
}
public Object method() {
System.out.println("the method is called");
return new Object();
}
}
#Test
public void testSt1() {
Dummy mock = EasyMock.createMock(Dummy.class);
EasyMock.expect(mock.method()).andAnswer(new IAnswer<Object>() {
#Override
public Object answer() throws Throwable {
System.out.println("mocked method is called");
return new Object();
}
} );
EasyMock.replay(mock);
mock.method();
}
#Test
public void testSt2() {
Dummy mock = EasyMock.createMock(Dummy.class);
EasyMock.expect(mock.method()).andDelegateTo(new Dummy(new Dummy(new Object()) {
#Override
public Object method() {
System.out.println("mocked method is called");
return new Object();
}
} );
EasyMock.replay(mock);
mock.method();
}
Results:
testSt1() does not call the constructor of Dummy
testSt2() calls the constructor of Dummy
What are the other differences?
The purpose of the two methods is to provide different levels of responsibility for your tests. Your example isn't that great, though.
Here's a simple method that demonstrates how functionally these two provide different test expectations.
public String foo() throws Exception {
throw new Exception();
}
With andAnswer, you can make a mocked version of this method return a String, even though it would never return one in practice. Your use of andAnswer implies an expected response.
With andDelegateTo, this will always throw an Exception. Your use of andDelegateTo implies an actual response.
andAnswer means your test-specific code will handle the response. For example, if you create a ParrotAnswer for a MockDao update method, the Parrot will return the updated Object, but no Dao is actually instantiated in the process. This is nice for unit testing where you basically walk the test subject through, but doesn't help if your mocked method doesn't do as what you method actually does.
andDelegateTo allows you to provide an actual Object implementing the interface to handle the response. We're allowing our test subject controlled access to a resource, rather than providing unrestricted access to a full resource. benefit of this is that you can test integration into a test environment, but minimize actual changes to the test environment. For example, you can delegate get to a wired Dao to fetch an actual live value from the Db, and mock the delete method, so you don't actually delete that same value during testing (and having to recreate it again later to do the same test if it has a static id, for example).
I'm trying to write a unit test that needs to confirm if a method is called or not. I'm using JUnit, Mockito and PowerMock.
public class Invoice
{
protected void createInvoice()
{
// random stuff here
markInvoiceAsBilled("57");
}
protected void markInvoiceAsBilled(String code)
{
// marked as billed
}
}
So, here my system under test is Invoice. I'm running this test:
public class InvoiceTest
{
#Test
public void testInvoiceMarkedAsBilled()
{
Invoice sut = new Invoice();
Invoice sutSpy = spy(sut);
sut.createInvoice();
// I want to verify that markInvoiceAsBilled() was called
}
}
This example is just an example of what the actual code looks like....
My problem is that mockito says you can only verify if a method is called on a mocked object... but I don't want to mock this object, as it's my object under test. I know that you can spy on the object you're testing, so here's what I tried:
verify(sutSpy).markInvoiceAsBilled("57");
Is what I'm trying to do not possible? Or am I just going about it the wrong way?
Thanks everyone :)
I'm not sure if what you are attempting to do is the best way to go about things.
I wouldn't concern myself with verifying that Invoice.createInvoice() calls an internal, private method markInvoiceAsBilled() - instead test that calling createInvoice() changes the state of the Invoice object in the way you expect - i.e., that status is now BILLED or something similar.
In other words - don't test what methods are called by createInvoice() - test that after calling this method, the state of the object is what you expect.
I agree with matt-b's answer. That being said, depending on the use case and the complexity of the method, you can redesign your unit so that it can be tested.
Say for example your object gets much more complicated, e.g.
public A {
public a() {
b();
c();
}
public b() { /** hairy code, many branches to test */ }
public c() { /** hairy code, many branches to test */ }
}
Covering b with tests and c with tests is straight-forward, but covering a would seem like a hassle since you depend on methods b and c.
Consider instead this design
public A {
private final Dep mDep;
public a() {
mDep.b();
mDep.c();
}
public b() {
mDep.b();
}
public c() {
mDep.c();
}
// dependency abstraction we create to help test
static class Dep {
public b() { /** hairy code, many branches to test */ }
public c() { /** hairy code, many branches to test */ }
}
}
Now, testing A.a, A.b and A.c just requires you to verify your mDep is called (among whatever else the method does). Separately, you test A.Dep.b and A.Dep.c methods.
I want to back up my application's database before replacing it with the test fixture. I'm forced to use Junit3 because of Android limitations, and I want to implement the equivalent behavior of #BeforeClass an #AfterClass.
UPDATE: There is now a tool (Junit4Android) to get support for
Junit4 on Android. It's a bit of a kludge but should work.
To achieve the #BeforeClass equivalent, I had been using a static variable and initializing it during the first run like this, but I need to be able to restore the database after running all the tests. I can't think of a way of detecting when the last test has run (since I believe there is no guarantee on the order of test execution.)
public class MyTest extends ActivityInstrumentationTestCase2<MainActivity> {
private static boolean firstRun = true;
#Override
protected void setUp() {
if(firstRun) {
firstRun = false;
setUpDatabaseFixture();
}
}
...
}
From the junit website:
Wrapped the setUp and tearDown method in the suite.This is for the
case if you want to run a single YourTestClass testcase.
public static Test suite() {
return new TestSetup(new TestSuite(YourTestClass.class)) {
protected void setUp() throws Exception {
System.out.println(" Global setUp ");
}
protected void tearDown() throws Exception {
System.out.println(" Global tearDown ");
}
};
}
If you would like to run only one setUp and tearDown for all the
testcase, make a suite and add testClass to it and pass the suite
object in TestSetup constructor.But I think there is not much usage
for this,and in a way it is violating JUnit philosophy.
Recently, I was looking for a similar solution too. Fortunately, in my case after the JVM exits after the last test is run. So I was able to achieve this by adding a JVM shutdown hook.
// Restore database after running all tests
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
restoreDatabase();
}
});
hope this helps.
I would suggest avoiding these kind of dependencies where you need to know the order in which tests are run. If all you need is to restore a real database that was replaced by setUpDatabaseFixture() probably you solution comes from the use of a RenamingDelegatingContext. Anyway, if you can't avoid knowing when the last test was run, you can use something like this:
...
private static final int NUMBER_OF_TESTS = 5; // count your tests here
private static int sTestsRun = 0;
...
protected void tearDown() throws Exception {
super.tearDown();
sTestsRun += countTestCases();
if ( sTestsRun >= NUMBER_OF_TESTS ) {
android.util.Log.d("tearDow", "*** Last test run ***");
}
}
Isn't this (dealing elegantly with data, so you don't have to worry about restoring it) what testing with mock objects are for? Android supports mocking.
I ask as a question, since I've never mocked Android.
In my experiences, and from this blog post, when the Android tests are made into a suite and run by the InstrumentationTestRunner - ActivityInstrumentationTestCase2 is an extension of ActivityTestCase which is an extendsion of InstrumentationTestCase - they are ordered alphabetically using android.test.suitebuilder.TestGrouping.SORT_BY_FULLY_QUALIFIED_NAME, so you can just restore you DB with a method that is the lowes in the alphabet out of your test names, like:
// underscore is low in the alphabet
public void test___________Restore() {
...
}
Note:
You have to pay attention to inherited tests, since they will not run in this order. The solution is to override all inherited test and simply call super() from the override. This will once again have everything execute alphabetically.
Example:
// Reusable class w only one time setup and finish.
// Abstract so it is not run by itself.
public abstract class Parent extends InstrumentationTestCase {
#LargeTest
public void test_001_Setup() { ... }
#LargeTest
public void test_____Finish() { ... }
}
/*-----------------------------------------------------------------------------*/
// These will run in order shown due to naming.
// Inherited tests would not run in order shown w/o the use of overrides & supers
public class Child extends Parent {
#LargeTest
public void test_001_Setup() { super.test_001_Setup(); }
#SmallTest
public void test_002_MainViewIsVisible() { ... }
...
#LargeTest
public void test_____Finish() { super.test_____Finish(); }
}