I like testing similar types of classes with the same code, so I don't forget to do stuff. Using JUnit4 (technically Junit3) I created classes like this:
#RunWith(AllTests.class)
public class MyPojoTest {
public static TestSuite suite() {
return PojoTestSuite.forPojoClass(MyPojo.class)
// test Serializable is implemented correctly
.serializable()
// test Comparable is implemented correctly
.comparable()
// etc.
.cloneable()
// creates a junit.framework.TestSuite
.create();
}
}
public class PojoTestSuite {
public static PojoTestSuite forPojoClass(Class<?> pojoClass) {
return new PojoTestSuite(pojoClass);
}
public TestSuite create() {
final TestSuite suite = new TestSuite();
suite.addTest(new EqualsTest());
suite.addTest(new HashCodeTest());
if (this.serializable) {
suite.addTest(new SerializeableTest());
}
if (this.cloneable) {
suite.addTest(new CloneableTest());
}
if (this.comparable) {
suite.addTest(new ComparableTest());
}
return suite;
}
// getters and setters, constructor, ...
}
However I wasn't able to implement something like it in pure JUnit4 and now in JUnit5 I can't find anything like it either.
Is there any way to use test suites to create a set of tests dynamically? I'd like to have the tests as small as possible, because having "testEqualsReturnsTrueForSameObject()" fail is a lot more useful than having "testPojo()" fail.
Related
I’m using Mockito 1.9.5. How do I mock what is coming back from a protected method? I have this protected method …
protected JSONObject myMethod(final String param1, final String param2)
{
…
}
However, when I attempt to do this in JUnit:
final MyService mymock = Mockito.mock(MyService.class, Mockito.CALLS_REAL_METHODS);
final String pararm1 = “param1”;
Mockito.doReturn(myData).when(mymock).myMethod(param1, param2);
On the last line, I get a compilation error “The method ‘myMethod’ is not visible.” How do I use Mockito to mock protected methods? I’m open to upgrading my version if that’s the answer.
This is not an issue with Mockito, but with plain old java. From where you are calling the method, you don't have visibility. That is why it is a compile-time issue instead of a run-time issue.
A couple options:
declare your test in the same package as the mocked class
change the visibilty of the method if you can
create a local (inner) class that extends the mocked class, then mock this local class. Since the class would be local, you would have visibility to the method.
Responding to the request for a code sample of option 3 from John B's answer:
public class MyClass {
protected String protectedMethod() {
return "Can't touch this";
}
public String publicMethod() {
return protectedMethod();
}
}
#RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
class MyClassMock extends MyClass {
#Override
public String protectedMethod() {
return "You can see me now!";
}
}
#Mock
MyClassMock myClass = mock(MyClassMock.class);
#Test
public void myClassPublicMethodTest() {
when(myClass.publicMethod()).thenCallRealMethod();
when(myClass.protectedMethod()).thenReturn("jk!");
}
}
You can use Spring's ReflectionTestUtils to use your class as it is and without needing of change it just for tests or wrap it in another class.
public class MyService {
protected JSONObject myProtectedMethod(final String param1, final String param2) {
return new JSONObject();
}
public JSONObject myPublicMethod(final String param1) {
return new JSONObject();
}
}
And then in Test
#RunWith(MockitoJUnitRunner.class)
public class MyServiceTest {
#Mock
private MyService myService;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(myService.myPublicMethod(anyString())).thenReturn(mock(JSONObject.class));
when(ReflectionTestUtils.invokeMethod(myService, "myProtectedMethod", anyString(), anyString())).thenReturn(mock(JSONObject.class));
}
}
Something like following worked for me, using doReturn() and Junit5's ReflectionSupport.
[Note: I tested on Mockito 3.12.4]
ReflectionSupport.invokeMethod(
mymock.getClass()
// .getSuperclass() // Uncomment this, if the protected method defined in the parent class.
.getDeclaredMethod("myMethod", String.class, String.class),
doReturn(myData).when(mymock),
param1,
param2);
John B is right, this is because the method you're trying to test is protected, it's not a problem with Mockito.
Another option on top of the ones he has listed would be to use reflection to gain access to the method. This will allow you to avoid changing the method you are testing, and avoid changing the pattern you use to write tests, and where you store these tests. I've had to do this myself for some tests where I was not allowed to change the existing code base which included a large number of private methods that needed to be unit tested.
These links explain Reflection and how to use it very well, so I will link to them rather than copy:
What is reflection and whit is it useful
How to test a class that has private methods, fields, or inner classes
WhiteBox.invokeMethod() can be handy.
public class Test extend TargetClass{
#Override
protected Object method(...) {
return [ValueYouWant];
}
}
In Spring, you can set it high high-priority like this:
#TestConfiguration
public class Config {
#Profile({"..."})
#Bean("...")
#Primary // <------ high-priority
public TargetClass TargetClass(){
return new TargetClass() {
#Override
protected WPayResponse validate(...) {
return null;
}
};
}
}
It is the same to override the origin bean.
I have two test functions and for each I want to have different #Before methods. How to achieve this ?
Although it seems to be convenient to organize all the test under the same class, for your case I think the best option is to separate the tests into different classes, each one with his corresponding setUp.
An alternative (I prefer the previous option) could be call the setUp directly in your test method, like the example as follows:
public class FooTest {
public void setUpMethod1() {
// do setUp things
}
public void setUpMethod2() {
// do setUp things
}
#Test
public void testMethod1() {
setUpMethod1();
// Test
}
#Test
public void testMethod2() {
setUpMethod2();
// Test
}
}
Only as a curiosity (IMO not recomended for your case), you can override the default junit RunListener with your own implementation. Method testStarted is executed before every test and you have access to class and methodName to be able to identify the running test. Dummy sample:
public class MyRunListener extends RunListener {
#Override
public void testStarted(Description description) throws Exception {
//...
Class testClass = description.getClass();
String methodName = description.getMethodName();
//...
}
}
Hope it helps.
Having trouble with this. I've used Powermockito quite a bit in the past. Normally this is pretty smooth. I figured I'd post my problem rather than continue to rummage through examples. So the goal is to verify a call to new for a class. I don't think this is the most popular feature of powermockito.
Here's the test:
import static org.powermock.api.mockito.PowerMockito.verifyNew;
import static org.powermock.api.mockito.PowerMockito.whenNew;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassUnderTest.class)
public class VerifyNewTest {
ClassUnderTest myClassUnderTest = new ClassUnderTest();
#Before
public void setUp() throws Exception {
}
#Test
public void test() throws Exception {
whenNew(Collaborator.class).withNoArguments().thenReturn(new Collaborator());
myClassUnderTest.doSomething();
verifyNew(Collaborator.class).withNoArguments();
}
}
and said classes
public class ClassUnderTest {
public void doSomething() {
new Collaborator();
}
}
public class Collaborator {
}
My goal was to make this as simple as possible. I suppose I could have added some mock objects and stubbed some behavior. Anyway, I get.
org.mockito.exceptions.misusing.UnfinishedStubbingException: Unfinished stubbing detected here:
-> at org.powermock.api.mockito.internal.invocationcontrol. MockitoNewInvocationControl.expectSubstitutionLogic(MockitoNewInvocationControl.java:65)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, you naughty developer!
Return a mock object in the whenNew() clause would work in your case.
#Test
public void test() throws Exception {
whenNew(Collaborator.class).withNoArguments().thenReturn(mock(Collaborator.class));
myClassUnderTest.doSomething();
verifyNew(Collaborator.class).withNoArguments();
}
The title pretty much says it all. I would like to set up a traditional JUnit test to mock a controller's dependencies and run tests against actions.
I've found that I can achieve my goal like this:
public class AccountsControllerTest {
private controllers.Accounts accountsController;
#Test
public void test() {
running(fakeApplication(), new Runnable() {
public void run() {
accountsController = new controllers.Accounts();
accountsController.setAccountsWorkflow(mock(workflow.Accounts.class));
}
});
}
}
The obvious problem here is that I'm instantiating my class under test and injecting mock dependencies from the test method itself, when I should be doing that in the setup() method. It seems that the setup() method is useless if I'm going to test my controller in a traditional way.
Of course I can test controllers the way Play recommends, but my application is dependent on an external SOAP web service, so I need unit tests to show that our code is working when their servers are down.
So, what's the best way to unit test a Play controller using mocks while still taking advantage of setup() and teardown() methods?
Edit
I realize I'm assuming some knowledge here, so for those who are unaware, controller instantiation in a unit test must be wrapped in a running() function or Play! will throw a runtime exception saying that no application has been started.
You could accomplish this using Mockito and Play's FakeApplication and setting the static Http.Context variable.
This way you can write the test like all other JUnit test.
Example:
...
import static play.test.Helpers.status;
import play.test.FakeApplication;
import play.test.Helpers;
import play.mvc.Http;
import play.mvc.Result;
...
#RunWith(MockitoJUnitRunner.class)
public class ApplicationTest {
public static FakeApplication app;
#Mock
private Http.Request request;
#BeforeClass
public static void startApp() {
app = Helpers.fakeApplication();
Helpers.start(app);
}
#Before
public void setUp() throws Exception {
Map<String, String> flashData = Collections.emptyMap();
Http.Context context = new Http.Context(request, flashData, flashData);
Http.Context.current.set(context);
}
#Test
public void testIndex() {
final Result result = Application.index();
assertEquals(play.mvc.Http.Status.OK, status(result));
}
#AfterClass
public static void stopApp() {
Helpers.stop(app);
}
In Junit 4 we add test suites using annotations as mentioned below:
#RunWith(Suite.class)
#SuiteClasses({
A.class, B.class })
public class MyTestsuite
{
}
My query is, do we have any way to specify condition to decide which classes i wanted to include in the #SuiteClasses. For example; lets say in the above code, if i wanted to class A if some particular condition is true, else i don't want to add it to #SuiteClasses.
In junit 3.8 we do it using suite() method like mentioned below:
public class MyTestsuite extends TestCase
{
public static Test suite()
{
TestSuite suite = new TestSuite();
if(some_condition_true)
{
suite.addTest(A.suite);
}
suite.addTest(B.suite);
return suite;
}
}
Is there any way we can achieve this using junit 4?
Extend Suite:
#RunWith(MySuite.class)//Customized
#SuiteClasses({
A.class, B.class })
public class MyTestsuite
{}
Define MySuite:
public class MySuite extends Suite {
public MySuite(Class<?> klass, RunnerBuilder builder)
throws InitializationError {
super(klass, builder);
try {
filter(new Filter() {
#Override public boolean shouldRun(Description description) {
return some_condition_true? true : false;
}
#Override
public String describe() {
return "...";
}
});
} catch (NoTestsRemainException e) {
System.out.println("Hey, all test cases are not satisfied your condition.");
}
}
}
plus: Although it can work, I recommend keep the test case simple. It is hard to maintain complex thing.
Shengyuan answer will work.
Another option is to always add the test class, but have an assumeTrue(condition) in your class that will decide when it should run and when it doesn't make sense.
(I like that approach better when the condition is related to test prerequisites: the test itself is the best place to know if it should run or not).