Ok, I know this is considered an anti-pattern, and I am certainly open to a better way of doing this.
I have a map of enum values. I want to ensure that each of those enum values is assigned to something. My test looks like this.
#Test
public void eachRowRequiresCellCalc()
{
Model model = new Model();
EnumValues[] values = EnumValues.values();
for (EnumValues value : values)
{
Assert.assertTrue(String.format("%s must be assigned", value.name()), model.hasEnumValue(value));
}
}
This works and accomplishes 90% of what I'm looking for. What it doesn't do is show me if multiple enum values are unassigned (it fails on the first). Is there a way with JUnit to have multiple fails per test?
Ideally you would not want to check for all values once you get a failure since it is anyways going to fail.
But a workaround I would suggest, but not sure if it works for you:
#Test
public void eachRowRequiresCellCalc()
{
Model model = new Model();
EnumValues[] values = EnumValues.values();
List<EnumValues> isFalse = new ArrayList<EnumValues>;
for (EnumValues value : values)
{
if(!model.hasEnumValue(value)) {
isFalse.add(value);
}
}
//Now you have the array of incorrect values in 'isFalse'
}
You cannot have multiple fails per test. But you can do something similar by tracking the failures in the for loop. Then outside the for loop print out your string in a single assert.
#Test
public void eachRowRequiresCellCalc()
{
Model model = new Model();
EnumValues[] values = EnumValues.values();
String errors = "";
for (EnumValues value : values)
{
if(!model.hasEnumValue(value))
errors += String.format("%s must be assigned", value.name()+". ");
}
if(!errors.isEmpty()){
fail(errors);
}
}
A way to express this using junit-quickcheck would be:
#RunWith(Theories.class)
public class Models {
#Theory public void mustHaveValue(#ForAll #ValuesOf EnumValues e) {
assertTrue(e.name(), new Model().hasEnumValue(e));
}
}
This would run the theory method for every value of your enum.
Another way to express this would be via a parameterized test.
(Full disclosure: I am the creator of junit-quickcheck.)
I know you asked about JUnit, but if you are in a position to consider TestNG, you can define a method as #DataProvider, which will supply parameters to a #Test method. What you seem to be looking for fits this perfectly.
Another option that comes to mind is that you might want to look into MatcherAssert.assertThat with collections matchers. Also it has better logging for your asserts - you might not need to use string format.
A suggestion regarding unit tests, if you don't mind: If you brake down a test method into blocks of given - when - then parts, it greatly improves their readability. given sets up the test case (variables, mocks, etc), when executes the method that is being tested, then is the part where you check the result (assert, verify, ...). I have found that following this structure helps others as well as myself weeks after the test has been written to understand what is going on.
I am aware this is an older question, but for anyone who stumbles upon it now, like I did - as of today, JUnit provides an assertAll() function, which can be used just for that, so there's no more need to fiddle around trying to get the results of multiple chained assertions :)
Here's the reference, hope this saves you some time! Would for sure have saved some of mine if I had known about it earlier.
Related
What is the way to test the methods when there are two public methods and a method calls another public method in the same class?
How should I write unit tests in this scenario?
An example
class SpecificIntMath {
public int add(int a,int b) {
return a+b;
}
public int multiply(int a, int b) {
int mul = 0;
for(int i = 0;i<b,i++) {
mul=add(a,mul);
}
return mul;
}
}
This example doesn't show the complexity of both the methods involved but the concept.
Should I test add and multiply separately? If I should test multiply only, I feel like we miss out cases where multiple cannot provide parameters.
Assuming multiply and add to be tested separately, should I be able to mock add? How is that possible?
Assuming multiply and add to be tested separately and I shouldn't mock, should I let add perform as it is. If this is the case how should I deal with the flow of the program inside add?
What is the approach to test such a kind of situation.
Edit 1:
In the below code,
class MCVC {
public boolean getWhereFrom(List<User> users) {
boolean allDone = true;
for(User user: users){
String url = user.getUrl();
switch(url) {
case Consts.GOOGLE:
someDao.updateFromAddr(user);
user.setEntry("Search Engine");
break;
case Consts.FACEBOOK:
someDao.updateFromAddr(user);
user.setEntry("Social Media");
break;
case Consts.HOME:
someDao.updateToAddr(user);
user.setEntry("Company");
default
user.setEntry(null);
allDone = false;
break;
}
}
return allDone;
}
public void likedDeck() {
List<Users> usersList = deckDao.getPotentialUsers(345L,HttpStatus.OK);
boolean flag = getWhereFrom(usersList);
if(flag) {
for(User user: usersList) {
//some Action
}
}
}
}
Should I consider getWhereFrom() while testing likedDeck() or should I assume any default situation? If I consider default situation, I lose out on cases where the output isn't default. I am not sure I should mock it since class which is calling is being tested. Spying/Mocking class under test
You don't care.
You use unit-testing to test the contract of each public method on its own. Thus you write tests that make sure that both add() and multiply() do what they are supposed to do.
The fact that the one uses the other internally is of no interest on the outside. Your tests should neither know nor care about this internal implementation detail.
And just for the record: as your code is written right now; you absolutely do not turn to mocking here. Mocking is not required here; and only adds the risk of testing something that has nothing to do with your real production code. You only use mocking for situations when you have to control aspects of objects in order to enable testing. But nothing in your example code needs mocking to be tested. And if it would - it would be an indication of poor design/implementation (given the contract of those methods)!
Edit; given the changes example in the question:
First of all, there is a bug in getWhereFrom() - you iterate a list; but you keep overwriting the return value in that list. So when the first iteration sets the result to false; that information might be lost in the next loop.
I see two options for the actual question:
You turn to Mockito; and its "spy" concept to do partial mocking; in case you want to keep your source code as is
Me, personally; I would rather invest time into improving the production code. It looks to me as getWhereFrom() could be worth its own class (where I would probably not have it work on a list of users; but just one user; that also helps with returning a single boolean value ;-). And when you do that, you can use dependency injection to acquire a (mocked) instance of that "WhereFromService" class.
In other words: the code you are showing could be reworked/refactored; for example to more clearly follow the SRP. But that is of course a larger undertaking; that you need to discuss with the people around you.
At least test them both seperatly. That the multiply test implicitly tests the add is no problem. In most of this cases you should ask yourself the question if it is necessary that both methods need to be public.
Should I test add and multiply separately?
You should test them separately, if you are doing unit testing. You would only like to test them together when doing component or integration tests.
Assuming multiply and add to be tested separately, should I be able to
mock add?
yes
How is that possible?
use mockito or any other mocking framework. Exactly how you can see here Use Mockito to mock some methods but not others
Assuming multiply and add to be tested separately and I shouldn't
mock, should I let add perform as it is.
I wouldn't do that. Internal changes in add could affect the tests from multiply and your tests would get more complicated and unstable.
A Sample can be deleted if status is S or P. I have this tests:
#Test
public void canBeDeletedWhenStatusIsP() {
Sample sample = new Sample();
sample.setState("P");
assertTrue(sample.canBeDeleted());
}
#Test
public void canBeDeletedWhenStatusIsS() {
Sample sample = new Sample();
sample.setState("S");
assertTrue(sample.canBeDeleted());
}
Should I go further? How should I test when the sample can't be deleted? For example:
#Test
public void cantBeDeletedWhenStatusINeitherPNorS() {
Sample sample = new Sample();
sample.setState("Z");
assertFalse(sample.canBeDeleted());
}
Is this test useful? What about the test naming? Would be this logic tested enough?
SaintThread is giving you a good "direct" answer.
But lets step back. Because you are doing something wrong in your production code. Most likely, your production code does something like a switch on that String that denotes the sample state. And not only once, but within all the methods it provides. And ... that is not a good OO design!
Instead, you should use polymorphism, like:
abstract class Sample {
boolean canBeDeleted();
// ... probably other methods as well
with and various concrete subclasses, like
class ZSample extends Sample {
#Override canBeDeleted() { return false; }
// ...
And finally, you have
class SampleFactory {
Sample createSampleFrom(String stateIdentifier) {
// here you might switch over that string and return a corresponding object, for example of class ZSample
And then, your tests boil down to:
Testing the factory; example for input "Z", it returns an instance of ZSample
Testing all your subclasses of Sample; for example that canBeDeleted() returns false for an instance of ZSample
The point is: your code does do the work of a FSM (finite state machine). Then don't use if/elses all over the place; instead, do the OO thing: create an explicit state machine. And, free bonus: this approach would also make it possible to turn your Sample objects into immutable thingies; which is most often better than having to deal with objects that can change their state over time (as immutability helps a lot with multi-threading issues for example).
Disclaimer: if your "Sample" class is only about that one method, maybe the above is overkill. But in any other case ... maybe step back and see if my suggestions would add value to your design!
In my opinion you should test:
cantBeDeletedWithoutStatus
assertFalse(sample.canBeDeleted());
cantBeDeletedWhenStatusIsInvalid
sample.setState("Z");
assertFalse(sample.canBeDeleted());
cantBeDeletedWhenStatusIsToggledToInvalid
sample.setState("P");
sample.setState("Z");
assertFalse(sample.canBeDeleted());
canBeDeletedWhenStatusIsToggledToS
sample.setState("Z");
sample.setState("S");
assertFalse(sample.canBeDeleted());
canBeDeletedWhenStatusIsToggledToP
sample.setState("Z");
sample.setState("P");
assertFalse(sample.canBeDeleted());
Let me know your thoughts in the comments
We should want our tests to be thorough, so they are likely to detect many classes of bugs. So the simple answer is yes, test the no-op case.
You don't tell what the possible values to the state. Let us assume they must be uppercase English letters, giving 26 states. Your question is then essentially the same as "should I have 26 test cases". That is many, but not prohibitive many. Now imagine a more complex case, for which the state is an int and all int values are possible. Testing them all thoroughly would be impractical. What to do?
The means for dealing with testing when there are very many inputs or initial states is to use equivalence partitiong. Divide the inputs or states into sets of inputs and sets of states, such that all the elements in a set should result in the same behaviour and are adjacent to each other. So in your case the equivalence partitions might be A-O, P, Q-R,S, T-Z. Then have one test case for each partition.
Say in the main code, you've got something like this:
MyClass.java
public class MyClass {
public List<Obj1> create(List<ObjA> list) {
return (new MyClassCreator()).create(list);
}
// Similar methods for other CRUD operations
}
MyClassCreator.java
public class MyClassCreator {
Obj1Maker obj1Maker = new Obj1Maker();
public List<Obj1> create(List<ObjA> list) {
List<Obj1> converted = new List<Obj1>();
for(ObjA objA : list)
converted.add(obj1Maker.convert(objA));
return converted;
}
}
Obj1Maker.java
public class Obj1Maker {
public Obj1 convert(ObjA objA) {
Obj1 obj1 = new Obj1();
obj1.setProp(formatObjAProperty(objA));
return obj1;
}
private String formatObjAProperty(ObjA objA) {
// get objA prop and do some manipulation on it
}
}
Assume that the unit test for Obj1Maker is already done, and involves a method makeObjAMock() which mocks complex object A.
My questions:
For unit testing MyClassCreator, how would I test create(List<ObjA> list)? All the method really does is delegate the conversion from ObjA to Obj1 and runs it in a loop. The conversion itself is already tested. If I were to create a list of ObjA and tested each object in the list of Obj1 I get back, I would have to copy makeObjAMock() into MyClassCreator's unit test. Obviously, this would be duplicate code, so is using verify() enough to ensure that create(List list) works?
For unit testing MyClass, again, its create(List<ObjA>) method just delegates the operation to MyClassCreator. Do I actually need to test this with full test cases, or should I just verify that MyClassCreator's create method was called?
In the unit test for Obj1Maker, I checked that the properties Obj1 and ObjA corresponded to each other by doing assertEquals(obj1.getProp(), formatObjAProperty(objA)). However, that means I had to duplicate the code for the private formatObjAProperty method from the Obj1Maker class into its unit test. How can I prevent code repetition in this case? I don't want to make this method public/protected just so I can use it in a unit test. Is repetition acceptable in this case?
Thanks, and sorry for the lengthy questions.
My opinion is here. Picking which methods to test is a hard thing to do.
You have to think about a) whether you are meeting your requirements and b) what could go wrong when someone stupid makes changes to the code in the future. (Actually, the stupid person could be you. We all have bad days.)
I would say, writing new code to verify the two objects have the same data in two formats would be a good idea. Probably there is no reason to duplicate the code from the private method and copying the code over is a bad idea. Remember that you are verifying requirements. So if the original string said "6/30/13" and the reformatted one said "June 30th 2013", I would just hard code the check:
assertEquals("Wrong answer", "June 30th 2013", obj.getProp());
Add some more asserts for edge cases and errors. (In my example, use "2/30/13" and "2/29/12" and "12/1/14" to check illegal date, leap year day and that it gets "1st" not "1th" perhaps.)
In the test on the create method, I would probably just go for the easy error and verify that the returned array had the same number as the one passed in. The one I passed in would have two identical elements and some different ones. I'd just check that the identical ones came back identical and the different ones non-identical. Why? Because we already know the formatter works.
I wouldn't test the constructor but would make sure some test ran the code in it. It's good to make sure most of the code actually runs in a test to catch dumb errors like null pointers you missed.
The balance point is what you are looking for.
Enough tests, testing enough different things, to feel good about the code working.
Enough tests, testing obvious things, that stupid changes in the future will get found.
Not so many tests that the tests take forever to run and all the developers (including you) will put off running them because they don't want to wait or lose their train of thought while they run.
Balance!
I've been reading up on (and experimenting with) several Java mocking APIs such as Mockito, EasyMock, JMock and PowerMock. I like each of them for different reasons, but have ultimately decided on Mockito. Please note though, that this is not a question about which framework to use - the question really applies to any mocking framework, although the solution will look different as the APIs are (obviously) different.
Like many things, you read the tutorials, you follow the examples, and you tinker around with a few code samples in a sandbox project. But then, when it comes time to actually use the thing, you start to choke - and that's where I am.
I really, really like the idea of mocking. And yes, I am aware of the complaints about mocking leading to "brittle" tests that are too heavily coupled with the classes under test. But until I come to such a realization myself, I really want to give mocking a chance to see if it can add some good value to my unit tests.
I'm now trying to actively use mocks in my unit tests. Mockito allows both stubbing and mocking. Let's say we have a Car object that has a getMaxSpeed() method. In Mockito, we could stub it like so:
Car mockCar = mock(Car.class);
when(mockCar.getMaxSpeed()).thenReturn(100.0);
This "stubs" the Car object to always return 100.0 as the max speed of our car.
My problem is that, after writing a handful of unit tests already...all I'm doing is stubbing my collaborators! I'm not using a single mock method (verify, etc.) available to me!
I realize that I'm stuck in a "stubbing state of mind" and I'm finding it impossible to break. All this reading, and all this excitement building up to using mocks in my unit testing and... I can't think of a single use case for behavior verification.
So I backed up and re-read Fowler's article and other BDD-style literatures, and still I'm just "not getting" the value of behavior verification for test double collaborators.
I know that I'm missing something, I'm just not sure of what. Could someone give me a concrete example (or even a set of examples!) using, say, this Car class, and demonstrate when a behavior-verifying unit test is favorable to a state-verifying test?
Thanks in advance for any nudges in the right direction!
Well, if the object under test calls a collaborator with a computed value, and the test is supposed to test that the computation is correct, then verifying the mock colaborator is the right thing to do. Example:
private ResultDisplayer resultDisplayer;
public void add(int a, int b) {
int sum = a + b; // trivial example, but the computation might be more complex
displayer.display(sum);
}
Clearly, in this case, you'll have to mock the displayer, and verify that its display method has been called, with the value 5 if 2 and 3 are the arguments of the add method.
If all you do with your collaborators is call getters without arguments, or with arguments which are direct inputs of the tested method, then stubbing is probably sufficient, unless the code might get a value from two different collaborators and you want to verify that the appropriate collaborator has been called.
Example:
private Computer noTaxComputer;
private Computer taxComputer;
public BigDecimal computePrice(Client c, ShoppingCart cart) {
if (client.isSubjectToTaxes()) {
return taxComputer.compute(cart);
}
else {
return noTaxComputer.compute(cart);
}
}
I like #JB Nizet's answer, but here's another example. Suppose you want to persist a Car to a database using Hibernate after making some changes. So you have a class like this:
public class CarController {
private HibernateTemplate hibernateTemplate;
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
public void accelerate(Car car, double mph) {
car.setCurrentSpeed(car.getCurrentSpeed() + mph);
hibernateTemplate.update(car);
}
}
To test the accelerate method, you could just use a stub, but you wouldn't have a compete test.
public class CarControllerTest {
#Mock
private HibernateTemplate mockHibernateTemplate;
#InjectMocks
private CarController controllerUT;
#Test
public void testAccelerate() {
Car car = new Car();
car.setCurrentSpeed(10.0);
controllerUT.accelerate(car, 2.5);
assertThat(car.getCurrentSpeed(), is(12.5));
}
}
This test passes and does check the computation, but we don't know if the car's new speed was saved or not. To do that, we need to add:
verify(hibernateTemplate).update(car);
Now, suppose that if you try to accelerate past max speed, you expect the acceleration and the update not to happen. In that case, you would want:
#Test
public void testAcceleratePastMaxSpeed() {
Car car = new Car();
car.setMaxSpeed(20.0);
car.setCurrentSpeed(10.0);
controllerUT.accelerate(car, 12.5);
assertThat(car.getCurrentSpeed(), is(10.0));
verify(mockHibernateTemplate, never()).update(car);
}
This test will not pass with our current implementation of CarController, but it shouldn't. It shows you need to do more work to support this case and that one of the requirements is that you don't try to write to the database in this case.
Basically, verify should be used for exactly what it sounds like - to verify that something happened (or didn't happen). If the fact that it happened or didn't isn't really what you are trying to test, then skip it. Take the second example I made. One could argue that since the value wasn't changed, it doesn't really matter whether update was called or not. In that case, you can skip the verify step in the second example since the implementation of accelerate would be correct either way.
I hope it doesn't sound like I'm making a case for using verify a lot. It can make your tests very brittle. But it can also 'verify' that important things that were supposed to happen did happen.
My take on this is that every test case should contain EITHER
stubbing, plus one or more asserts OR
one or more verifys .
but not both.
It seems to me that in most test classes, you end up with a mixture of "stub and assert" test cases and "verify" test cases. Whether a test case does a "stub and assert" or does a "verify" depends on whether the value returned by a collaborator is important to the test. I need two examples to illustrate this.
Suppose I have an Investment class, which has a value in dollars. Its constructor sets the initial value. It has an addGold method, which increases the value of an Investment by the amount of gold times the price of gold in dollars per ounce. I have a collaborator called PriceCalculator that calculates the price of gold. I might write a test like this.
public void addGoldIncreasesInvestmentValueByPriceTimesAmount(){
PriceCalculator mockCalculator = mock( PriceCalculator.class );
when( mockCalculator.getGoldPrice()).thenReturn( new BigDecimal( 400 ));
Investment toTest = new Investment( new BigDecimal( 10000 ));
toTest.addGold( 5 );
assertEquals( new BigDecimal( 12000 ), toTest.getValue());
}
In this case, the result from the collaborator method is important to the test. We stub it, because we're not testing the PriceCalculator at this point. There's no need to verify, because if the method hadn't been called, the final value of the investment value would not be correct. So all we need is the assert.
Now, suppose there's a requirement that the Investment class notifies the IRS whenever anyone withdraws more than $100000 from an Investment. It uses a collaborator called IrsNotifier to do this. So a test for this might look like this.
public void largeWithdrawalNotifiesIRS(){
IrsNotifier mockNotifier = mock( IrsNotifier.class );
Investment toTest = new Investment( new BigDecimal( 200000 ));
toTest.setIrsNotifier( mockNotifier );
toTest.withdraw( 150000 );
verify( mockNotifier ).notifyIRS();
}
In this case, the test doesn't care about the return value from the collaborator method notifyIRS(). Or maybe it's void. What matters is just that the method got called. For a test like this, you'll use a verify. There may be stubbing in a test like this (to set up other collaborators, or return values from different methods), but it's unlikely that you'll ever want to stub the same method that you verify.
If you find yourself using both stubbing and verification on the same collaborator method, you should probably ask yourself why. What is the test really trying to prove? Does the return value matter to the test? Because this is usually a testing code smell.
Hope these examples are helpful to you.
I'm currently trying to build a more or less complete set of unit tests for a small library. Since we want to allow different implementations to exist we want this set of tests to be (a) generic, so that we can re-use it to test the different implementations and (b) as complete as possible. For the (b) part I'd like to know if there is any best-practice out there for testing enum types. So for example I have an enum as follows:
public enum Month {
January,
February,
...
December;
}
Here I want to ensure that all enum types really exist. Is that even necessary? Currently I'm using Hamcrests assertThat like in the following example:
assertThat(Month.January, is(notNullValue()));
A missing "January" enum would result in a compile time error which one can fix by creation the missing enum type.
I'm using Java here but I don't mind if your answer is for a different language..
Edit:
As mkato and Mark Heath have both pointed out testing enums may not be necessary since the compiler won't compile when you are using an enum type which isn't there. But I still want to test those enums since we want to build a seperate TCK-like test.jar which will run the same test on different implementations. So my question was more meant to be like: What is the best way to test enum types?
After thinking about it a bit more I changed the Hamcrest statement above to:
assertThat(Month.valueOf("January"), is(notNullValue()));
This statement now throws a NPE when January is not there (yet). Is there anything wrong with this approach?
For enums, I test them only when they actually have methods in them. If it's a pure value-only enum like your example, I'd say don't bother.
But since you're keen on testing it, going with your second option is much better than the first. The problem with the first is that if you use an IDE, any renaming on the enums would also rename the ones in your test class.
I agree with aberrant80.
For enums, I test them only when they actually have methods in them.
If it's a pure value-only enum like your example, I'd say don't
bother.
But since you're keen on testing it, going with your second option is
much better than the first. The problem with the first is that if you
use an IDE, any renaming on the enums would also rename the ones in
your test class.
I would expand on it by adding that unit testings an Enum can be very useful. If you work in a large code base, build time starts to mount up and a unit test can be a faster way to verify functionality (tests only build their dependencies). Another really big advantage is that other developers cannot change the functionality of your code unintentionally (a huge problem with very large teams).
And with all Test Driven Development, tests around an Enums Methods reduce the number of bugs in your code base.
Simple Example
public enum Multiplier {
DOUBLE(2.0),
TRIPLE(3.0);
private final double multiplier;
Multiplier(double multiplier) {
this.multiplier = multiplier;
}
Double applyMultiplier(Double value) {
return multiplier * value;
}
}
public class MultiplierTest {
#Test
public void should() {
assertThat(Multiplier.DOUBLE.applyMultiplier(1.0), is(2.0));
assertThat(Multiplier.TRIPLE.applyMultiplier(1.0), is(3.0));
}
}
Usually I would say it is overkill, but there are occasionally reasons for writing unit tests for enums.
Sometimes the values assigned to enumeration members must never change or the loading of legacy persisted data will fail. Similarly, apparently unused members must not be deleted. Unit tests can be used to guard against a developer making changes without realising the implications.
you can test if have exactly some values, by example:
for(MyBoolean b : MyBoolean.values()) {
switch(b) {
case TRUE:
break;
case FALSE:
break;
default:
throw new IllegalArgumentException(b.toString());
}
for(String s : new String[]{"TRUE", "FALSE" }) {
MyBoolean.valueOf(s);
}
If someone removes or adds a value, some of test fails.
If you use all of the months in your code, your IDE won't let you compile, so I think you don't need unit testing.
But if you are using them with reflection, even if you delete one month, it will compile, so it's valid to put a unit test.
This is a sample for what we have within our project.
public enum Role {
ROLE_STUDENT("LEARNER"),
ROLE_INSTRUCTOR("INSTRUCTOR"),
ROLE_ADMINISTRATOR("ADMINISTRATOR"),
ROLE_TEACHER("TEACHER"),
ROLE_TRUSTED_API("TRUSTEDAPI");
private final String textValue;
Role(String textValue) {
this.textValue = textValue;
}
public String getTextValue() {
return textValue;
}
}
class RoleTest {
#Test
void testGetTextValue() {
assertAll(
() -> assertEquals("LEARNER", Role.ROLE_STUDENT.getTextValue()),
() -> assertEquals("INSTRUCTOR", Role.ROLE_INSTRUCTOR.getTextValue()),
() -> assertEquals("ADMINISTRATOR", Role.ROLE_ADMINISTRATOR.getTextValue()),
() -> assertEquals("TEACHER", Role.ROLE_TEACHER.getTextValue()),
() -> assertEquals("TRUSTEDAPI", Role.ROLE_TRUSTED_API.getTextValue())
);
}
}