I want to create a new assertEquals which takes in as input a custom pojo for expected and actual.
How would I go about extending assertEquals of the JUnit library?
What I could do is implement a compare method which returns a boolean and have this as the input to the assertEquals or even assertTrue but creating my own assertEquals seems more elegant.
Would it simply be the case of returning true if equal or raising a AssertionError?
As #Makoto commented, you could use a custom Hamcrest Matcher.
The disadvantage of the other common answer here (just change the definition of Object#equals for your class), is that you would have one and only one way of comparing your objects, and it would have to match exactly what is needed by the test rather than what would be needed by users of the class. The two needs may or may not be identical. Often in testing, I only need to assert one or two values, sometimes several, but usually not what gets tested by the "natural" #equals method of my class. Furthermore, I work with a lot of classes that don't even have an explicit override of #equals. In these cases you would have to define one that works simply for the case of your test, whereas it semantically might not represent the domain very well.
There is an overload of assertEquals that takes objects. It (eventually) calls the equals method on both objects. So, the "compare" method you need to write is an override of Object's equals method.
Once you have that written, then you can call assertEquals("Failure message", yourObject1, yourObject2). There is no need to extend JUnit for this case.
As an aside, if you override equals, then you should override hashCode also, in a consistent way.
Asserts are static methods, defined in Assert class. TestCase derives from that class, hence all asserts are available there too.
java.lang.Object
|
+--junit.framework.Assert
|
+--junit.framework.TestCase
Creating another derived class, such as class MyTestCase extends TestCase and define your customized asserts there the same way they are defined in Assert.
Use MyTestCase instead of TestCase
Profit!
Another approach is to define proper equals() method and use standard assertEquals(). You can use EqualsBuilder to get a reasonable implementation automagically using reflection.
http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/builder/EqualsBuilder.html
If you don't like Apache Commons, you can find similar tool in Guava.
Related
Rule one of TDD is this:
Write production code only to pass a failing unit test
Effective Java Item 11(third edition), that is the same contract of java Object.hashCode():
Always override hashCode when you override equals
Now which is correct to do if we need to override only equals to pass a failed test and we need not to use object in a collection in the current failed test and it may be happened in future?
Always override hashCode when you override equals
Try this spelling: if you have to override equals, then your work is not done until you've also overridden hashCode.
So don't merge/share/publish the work until all of the required elements of the contract are complete.
But you can do the work in whatever order you like.
I've created a simple test class with two fields like
#Mock
private MyTestClass myTestClass;
#Spy
private final MyContext context = CommonTestData.getDefaultContext();
Basically I don't really need the spy functionality here, it is just used to automatically inject the object into other mocks.
For the test, I tried to configure myTestClass like this:
when(myTestClass.someMethod(eq(context))).thenReturn(someValue);
The problem now is, that Matchers.eq is not matching "un-enhanced" versions of MyContext. So when someMethod is called during the test with a "regular" instance of MyContext that actually equals the value used for context, the stubbed method is not called.
It seems like the Mockito enhanced MyContext class implements its own equals method, at least the equals method of MyContext never seems to be called. Thus, I currently can't think of any way to modify the actual comparison being done.
I can think of various workarounds for this issue like using a custom argument matcher or stubbing the method with an instance of the "real" object. I was however wondering: Is there any Mockito-provided solution to check for equality of enhanced classes against their regular counterparts?
This is conceptually wrong: the idea of equals() in Java is to be symmetric: when a.equals(b) then you better find that b.equals(a), too!
And in your case, a has class MyContext, and b has WhateverMockitoSpyDoesToMyContext. So even when the equals() of the mockito generated thing works, most likely the other way round, that "base" equals might return false (because the original MyContext class knows nothing about potential subclasses like what Mockito is doing here).
I agree that it might be convenient to have your example work out, but I am simply not aware of a "correct" way getting there. From that point of view, you actually have to look into use an ArgumentMatcher.
Beyond that: seriously consider if you really gain anything by using eq() in the first place. If that check is the "core" of your test, then sure, somehow you better look for clear ways to have that check. But if it is more of a byproduct: then just use any() instead.
Meaning: don't make your tests more complicated than necessary. Normally, you setup things for one specific case anyway. You only have to worry about things passed to someMethod() if your code under test could actually, correctly pass different objects to that method.
What is the best practice for verifying a method call with complex parameters when unit testing?
Say I'm testing a function like this:
class ClassA {
ClassB dependency;
void someFunction(SomeInputForA input) {
// do some thing
dependency.anotherFunction(differentInput);
}
}
The two options that I can think of for verifying that someFunction calls anotherFunction with the proper input are:
A) do a verify on the mock of dependency for calling anotherFunction
unitUnderTest.dependency = mockClassB;
InputClass expectedDifferentInput = ... ;
verify(mockClassB).anotherFunction(expectedDifferentInput);
B) do an argument captor on the call of anotherFunction and assert the properties
unitUnderTest.dependency = mockClassB;
ArgumentCaptor<InputClass> captor = ArgumentCaptor.for(InputClass.class);
verify(mockClassB).anotherFunction(captor.capture());
InputClass capturedInput = captor.getValue();
assertEquals(value, capturedInput.param1);
// and more asserts afterwards
Is there a suggested path here? I'd lean towards the captor method because it feels more rigorous and is not relying on objects equals implementations being proper.
Thoughts?
Is differentInput computated off input?
If so then your B) is the better way to go as you are saying for Input A, you expect ClassA to change this to expectedDifferentInput and want to verify the delegating class (ClassB) is called. You are verifying the transformation of the input and delegating logic of ClassA.
If differentInput has no relation to input then you don't need to use the captor as really you are just checking delegation.
Any public caller to someFunction on ClassA shouldn't need to know about ClassB so it can be said both methods A) and B) are actually white box testing, in this case and so you might as well use the captors anyway. As you vary your input to someFunction, captors may also help you to identify edge cases if differentInput is computed off input.
You can always use matchers on the object passed into mockClassB.anotherFunction(). For example, if you want to compare fields on an object, you can write:
Matcher<YourClass> yourMatcher = Matchers.hasProperty("yourProperty", Matchers.equals(whatever));
verify(mockClassB).anotherFunction(argThat(yourMatcher));
I prefer this way, since you can share syntax for the when and the verify for the matchers and you can combine any combination of matchers. You just need to include the latest mockito and hamcrest libraries to get this to work.
I've used argument captors but VERY sparingly. The biggest issue you run into is that this route creates fragile unit tests. And no one is happy when they make a small change to a class and then find themselves struggling with unit tests in calling classes that shouldn't have been affected.
That being said, absolutely you have to eventually ensure that correct calls are made. But if you rely on an equals override working, then you are relying on that class having an equals method that works, and this is then part of that class's contract (and unit tested in that class) which is reasonable.
So that's why I'd vote for keeping it simple and just using verify. Same thing in the end, but your unit test is just less fragile.
I have some third party code that has a lot of classes with broken equals() and hash-code implementations. I cannot change the third-party code but need the equals method badly. To overcome this I came up with the the following approaches:
1) Create an EqualsUtility which has a bunch of overloaded static equals() methods.
Problem: the class will become very large as the third-party code grows.
2) Create adapter classes for all the third party classes and write an equals method.
Problem: Too many new classes are created.
Is there a third, more clean way to do this.
You may try to check the object equality with some 3rd party lib, for example with the ApacheCommoms EqualsBuilder. But that could be not a very good solution, since it uses reflection for comparison. Furthermore, it doesn't help with hash code implementation.
IMO, extending base classes and overriding equals and hashcode methods are prefferable. Any other solution, including aspects, 3rd party libs for deep object comparison, some proxy objects, are not good for performance and in some cases for understanding of your code.
Check out AspectJ. It's an Aspect Oriented programming library for Java that let's you do exactly what you want to do. You describe an entity called a pointcut that corresponds roughly to in this case a method invocation of the equals() method on the library's objects.
You then write code that gets executed when that pointcut is hit. You can write different types of pointcuts. So for instance you can have your code execute before the equals() method, after the equals() method, or around the equals() method. If you write an around() type you can choose to handle the call your self or do some work then call the original method.
You could do an around() and rewrite the equals method so it is correct for your situation.
Very powerful stuff.
I'm using easymock, and I am mocking my UserService class.
My UserService has a few methods:
boolean canUserLogin(..);
boolean canUserJoinClass(...);
Now some of the methods call each other, and if I am testing method#1 I want to stub/mock methods #2 and methods# 3 that are called in method#1.
What I am confused is, how can I mock parts of a class and leave others to run the actual code?
So I want to actually test UserService.method#1, but mock UserService.method#2 and UserService.method#3 that method#1 calls internally.
By specifying return values for the methods you want mocked; see the easymock docs for examples.
The "Specifying Return Values" section discusses creating return values for mocked methods.
The "Partial mocking" section (towards the bottom) discusses mocking actual classes.
I agree with the docs (and other answers) that this may be an indication of sketchy design. Without further details, it's hard to say how sketchy it is, if it is at all.
You can check some library like Easymock, but I don't sure whether it can do this.
And here is my solution without third-party library. Create a subclass of UserService, and override the method you want to mock.
class SubUserService{
#override
boolean canUserJoinClass(...){
return false;
}
}
But notice the mock method can't be private.
And if this is one real problem you meet, you should refactor you methods to different classes.
I know Mockito supports "spy" on real objects. I could not find an equivalent in Easy Mock. So, I am not sure if you can do this.
Having said that, this is a smell to me. Why do you need to mock it? Is that an indication of the fact that your object is doing too much and hence you need to mock the other interactions?
Also, whenever you need to worry about the implementation of a method (method 1 in this case) i.e. the fact that it calls method2 and method3, especially of the same class, that sounds to me like a encapsulation leaking.
Mocking is intended to be used for dependencies, so you can test in isolation. In this case, you don't have any dependencies, since the methods you are calling are on one class. So I wouldn't use mocking here.
If methods 2 and 3 are so complicated that you want to mock them when testing method 1, then perhaps you should separate them out into their own class(es), so you can easily mock them.