I have two tests they are exactly the same... barring two things, they call two separate service calls.. hence when im using mockito i have two seperate expectation and verify lines...
this is what i have done:
#test
TestA {
baseTest("player");
}
#test
TestB {
baseTest("member");
}
BaseTest(type type) {
....
.....
if type(player) {
Mockito.when(player service call)
}
else {
Mockito.when(member service call)
}
// make the call in code
//verify
if(player) {
verify player specific service call...
}
else {
}
}
I think the above is a test smell... just doesnt feel right...
Is there a better way then placing an If statement in my baste test?
Anywhere you see repeated if statements like that, you can use polymorphism. You should make the "player service call" and "member service call" methods abstract in the superclass BaseTestSuper, which will also own the existing BaseTest method..
You should develope your test code independenly and join things when they have sense.
By example. One rule of thumb for initialization code (the first A of Arrange/Act/Assert) is that:
you should write all the Arrange part of a test method in the test.
if your method shares initialization with all the other methods, then put it in a #Setup method
if some test method doesn't share that initialization it's probably because it doesn't fit in that test case.
So my conclusion is:
write independent tests
if they share things you can refactor
but not too much (or in a weird thing like "if"s)!!! Adds complexity, not reuse.
In fact #artbristol answer makes sense: if you are using if's for alternate behaviour consider polymorphism. It's just I'm not sure until which point it's complex for test or not (probable it makes sense if the code is testing a similar class hierarchy).
I would still just implement the 2 test classes separately. Code length and duplication don't really matter for tests, code readability, thoroughness and correctness take priority. In that light, just implement the 2 test cases separately.
In general you should not add any complexity to your tests. First, you can make mistake there (even in simple ifs). Second, your tests are not a documentation anymore, meaning that you can not easily understand what is the scenario of usage and behaviour of the tested class.
So it is a smell. :)
Related
I'm writing a Junit 4 test class comprising of 5 test methods.
All these 5 test methods have same 10 assertEquals lines of code.
Would it be best practice to move these lines of codes in one method for e.g. public void callAssertions() { .... }
and call this method from all tests?
As matt freake's comment mentions - Calling Junit Assertions via method call, there are differing opinions, but what I would do is separate assertions that are similar in nature.
So for example if you want to assert person's details, I would separate them into an assertPersonDetails() method - and so forth for other assertions. It really depends on the business logic underneath.
I wouldn't recommend separating them all into a generic named method like you suggested callAssertions()
As with all code, you should make sure that every test and every method in your test is readable and comprehensible.
You should have a clear pattern in your top test methods: given X, when Y, then Z. You can extract common code from each of the given/then/when parts, but you should not mix them.
So an assertThatZzzIsConsistent(...) method is OK, if it extracts only from the 'then' part. But an executeYyyAndAssertThatZzzIsConsistent(...) is not OK if it combines the 'when' and 'then' part.
I think that is a neater solution yes. Personally i always keep everything as separate as possible so every test is completely standalone. As long as that is the case it's okay.
I want to test a function in my code. This function calls another function in the same class but in my test I don't want to call it (I don't need it). Somehow, my test always goes into that inner function and makes errors. Is there any means to "skip" the call to that inner function ?
Here's an example :
void function1() {
if(condition == true) {
variable1 = function2()
}
}
Object function2() {
//Do something
return Object;
}
Is there a way to avoid calling function 2 ?
Thank you.
First you should consider fixing those errors thrown from function2().
If however you want to test the function1() isolated then the behavior you are describing is called Test Doubles. One kind of those test doubles is Mocking where you can drive the behavior of a class or a method.
There are frameworks doing this such as Mockito, but of course you can solve that problem on your own not depending on frameworks.
For example if you use Mockito you should end up mocking the function2() method like this
YouClassName mockedClass = mock(YouClassName.class);
when(mockedClass.function2()).thenReturn(new Object()); //you can of course return anything here
Its pretty common to test functions in isolation but in times where are dependencies between objects. If there are no dependencies you should probably consider not using test doubles (unless you are sure what you are doing).
Frameworks such as Mockito offer concepts such as spies. Using a Mockito spy, you can gain full control over which methods get invoked.
But: you only do that for very specific cases.
When you have a hard time testing your production code, then most likely: because you have written hard to test code.
Thus: you could try to use a spy here, but I would rather advice to step back and re-think what exactly you intend to do here.
Is it a code smell to spy on an object that is being unit tested? For example say I have a LineCounter class whose job is to simply count the number of lines in a string. --
class LineCounter {
public int getNumLines(String string) {
String metadata = getStringMetadata(string);
// count lines in file
return numLines;
}
/** Expensive operation */
protected String getStringMetadata(String string) {
// do stuff with string
}
}
Now I want to write a JUnit 4 test for this to test the getNumLines method while mocking out the expensive getStringMetadata call. I decide to use Mockito's spy mechanism to have getStringMetadata return a dummy value.
class LineCounterTests {
#Test public void testGetNumLines() {
LineCounter lineCounterSpy = Mockito.spy(new LineCounter());
// Mock out expensive call to return dummy value.
Mockito.when(lineCounterSpy.getStringMetadata(Mockito.anyString()).thenReturn("foo");
assertEquals(2, lineCounterSpy.getNumLines("hello\nworld");
}
}
Is this a reasonable thing to do? I feel pretty weird testing a Spy object rather than the actual class, but I can't really think of a reason against it.
I will answer the question in two parts. First, yes it is code smell to mock or spy the class under test. That does not mean that it cannot be done correctly but that it is risk prone and should be avoided whenever possible.
WRT your specific example, I would see how the spy could be correctly used but that would be predicated on the assertion that you have elsewhere fully unit tested getStringMetadata. This then begs the question, if you have fully unit tested getStringMetadata elsewhere then you must know how to test it and therefore why not test getNumLines without the spy.
All this being said, millhouse makes a good point but either way you have to unit test the expensive code somewhere. His suggestion goes a long way to help isolate the expensive code and ensure that you only have to test / exercise it once.
In this situation, it is perfectly legitimate to stub the method that is called by the method under test. It is even the only way I can think of to test it in isolation. You just don't want to extract a single method into it's own class for the sole purpose of testing.
Beware of the side effects in the stubbed method though. It might not be sufficient to stub the returned value, if the stubbed method has side effects then you have to stub the side effects as well. It might even be a reason against it in some situations where the side effects are very complex, but that would most likely be an indication of a code smell in the implementation of the class under test itself.
To answer your question, I find it easy to find reasons for it, but hard to find reasons against it. It's the technique I use every day, it helps me split my implementation in small methods that are tested individually in complete isolation, and I haven't seen any limitation to it yet.
I'm trying to figure out the best way of writing a unit test for an overridden method which calls super() as the last step. Basically, I want to massage parameters before they're used in the base class.
Here's an example of a method:
#Override
public JobExecution run(Job job, JobParameters passedParams)
throws JobExecutionAlreadyRunningException, JobRestartException {
JobParameters launchParameters;
if(passedParams.isEmpty()) {
launchParameters = jobParameterSetter.getJobParameters();
} else {
launchParameters = passedParams;
}
return super.run(job, launchParameters);
}
What it comes down to is that I can't find a seam to check the parameters that are in the eventual super.run() call, which is all I want to test. The base class has several dependencies, and it's really not necessary to test that class (not to mention a lot more work).
Composition is a solution, but it's a fairly complicated base class and I need to expose the whole thing while only overriding a couple of methods.
I'm also considering faking the base class for testing, which is simple enough, but I'm not sure how to change the classpath just for running the unit test (Eclipse for single tests; Maven for build testing -- maybe a question on its own?).
I have to imagine this has already been asked, but I can't find an exact match.
It seems that the logic you are wanting to test is the if-else flow, and NOT the call to the base class. I would do this by creating a protected method called getLaunchParameters(JobParameters jobParameters), which does the bit of logic you are interested in testing.
This way, the logic you want tested is tested, the logic you are not interested in testing is not tested, and you have broken out a piece of code that may be able to be used else where in the future.
Lets say we have method to test in class A that calls method from class B. To test it we created mock for B and then verify if it was called. Is verify(...) enough for unit test or I need assert actual result of tested method?
Below is simplified example to clarify my concern:
public class StringWriterATest {
StringWriterB b = mock(StringWriterB.class);
#Test
public void stringWriterATest() {
StringBuffer sb = new StringBuffer();
StringWriterA a = new StringWriterA();
a.stringWriterB=b;
a.append(sb);
ArgumentCaptor<StringBuffer> argument = ArgumentCaptor.forClass(StringBuffer.class);
verify(b).append(argument.capture());
assertEquals("StringWriterA", ((StringBuffer)argument.getValue()).toString());
//do we really need this or above is enough for proper unit test of method a.append(sb);
//assertEquals("StringWriterA_StringWriterB", sb);
}
}
public class StringWriterA {
public StringWriterB stringWriterB;
public void append(StringBuffer sb) {
sb.append("StringWriterA");
stringWriterB.append(sb);
}
}
class StringWriterB {
public void append(StringBuffer sb) {
sb.append("StringWriterB");
}
}
Regards,
Max
There is never a need to mock a return value and verify an object at the same time.
Consider this:
StringWriterA is the class under test. Therefore you'll definitely want to use assertions to verify the behavior of this class. In order to do this, you mock out a dependency, StringWriterB.
You do not want to test StringWriterB in your test of StringWriterA, therefore any assertions of StringWriterB interactions in your test are in the wrong place.
You must assume that StringWriterB is behaving as expected. You either want to verify that StringWriterA called StringWriterB correctly (using verify()) or you want to mock its expected behavior and mock the return values.
If you mock, then the verify is implicit since the mocked return value will not be returned if the method is not called.
In your case, StringWriterA.append() does not return any value, so only a verify is even possible. That StringWriterB.append() also works should have a similar verify test in a stringWriterBTest of its own.
Note: It's nice to be explicit with tests. Since test methods are never called outside of a framework, there is never a need to type them out, so you can have much longer method names than in production code methods. A nice convention is:
<underTest>Should<Expected>[When]<Condition>()
i.e.
stringWriterAShouldAppendConstantAndDelegateToStringWriterB()
stringWriterAShouldThrowNullPointerExceptionWhenNullArgument()
When you have test failures in your build (continuous integration), then you don't have to hunt down what went wrong, the method name appears right by the failure and you can read it to know exactly what behavior must be fixed.
In your example, StringWriterB stores no state and the append method could easily be static. In that case then the call is purely a side effect and does not need to be tested.
However, I suspect your real code is much more complex. If there is a of another object accessing StringWriterB then you maye want to mock it out in case there are unexpected calls to it. You also may want to add the verify of B if you expect it to be expanded in the future -- possibly storing state from the append call and having accessors.
One thing to consider is what the purpose of the call to StringWriterA.append() is. If it's job is to append the string StringWriterAStringWriterB then that is what you should be testing and a mock is not necessary. How StringWriterA accomplishes that task is immaterial. If, however, part of its job is to also call the StringWriterB.append() method then a mock may will be necessary unless you want to test StringWriterB in A's test.
My rule of thumb WRT mocks is to use real objects until the wiring for the objects I'm not directly testing gets too hairy or too brittle. If I feel like a good portion of my tests are in actuality testing other objects then mocks would be a good idea.
First of all try to show somebody the test you wrote. It is hard to read in my opinion. You can't really tell from it what behaviour you are testing. A brief intro for you how to make it a bit more readable can be found here How to Write Clean, Testable Code .
Using argument captors is also a smell. Some examples how to avoid it can be found on this tdd blog.
To answer you question, verify is used to verify interactions between classes. It is used to drive the design of your code. The result (if needed) should be specified by a when or given at the beginning of your test.
Further information how to drive your design with mocks (when, given, verify, ...) and how mocks are different to stubs can be found here: Mocks are not stubs. That example uses JMock not Mockito for defining mocks, but it is very similar (it is about the concepts, not the details of implementation and libraries you use).