I have a maven Java project in Intellij IDEA community. The TestNg version is very old i.e. 6.9.5 and I simply cannot update it. I have 6 TestNg test methods in a class. Only 5/6 of these methods use data provider methods, all of which are in one DataProvider class.
When I run the test class, only the method without data provider (say test_5) runs successfully. The others are marked as "test ignored". Moreover, when I comment or disable test_5, then all the other tests run. Can I make testng give a detailed reason for ignoring tests ?
Here is brief information about my project. I can't give the full code.
public class MyUtilityClass {
public class MyUtilityClass(){
//Load data from property files and initialize members, do other stuff.
}
}
public class BaseTest {
MyUtilityClass utilObj = new MyUtilityClass();
//do something with utilObj, provide common annotated methods for tests etc.
}
public class TestClass extends BaseTest {
#BeforeClass
public void beforeMyClass(){
//Get some data from this.utilObj and do other things also.
}
#Test(dataProvider = "test_1", dataProviderClass = MyDataProvider.class)
test_1(){}
#Test(dataProvider = "test_2", dataProviderClass = MyDataProvider.class)
test_2(){}
...
//test_5 was the only one without data provider.
test_5(){}
#Test(dataProvider = "test_6", dataProviderClass = MyDataProvider.class)
test_6(){}
}
public class MyDataProvider {
MyUtilityClass utilObj = new MyUtilityClass();
//do something with utilObj besides other things.
}
Your tests need to end in exactly the same environment in which they started.
You gave nary a clue as to what your code is like, but I can say that it is almost certainly either a database that is being written to and not reverted or an internal, persistent data structure that is being modified and not cleared.
If the tests go to the database, try enclosing the entire test in a transaction that you revert at the end of the test. If you can't do this, try mocking out the database.
If it's not the DB, look for an internal static somewhere, either a singleton pattern or a static collection contained in an object. Improve that stuff right out of your design and you should be okay.
I could give you more specific tips with code, but as is--that's about all I can tell you.
I solved my problem. Test_5 is the only test method which does not have a data provider. So, I provided a mock data provider method for it.
Related
I've been trying to get this guide to work from Wiremock's documentation:
https://wiremock.org/docs/junit-jupiter/ - Advanced usage - programmatic
As I want to be able to mock multiple hosts simultaneously (same host, unique ports for my local environment). But I don't want these #RegisterExtension to be located in my test classes, instead in separate files but in doing so JUnit doesn't pick them up and I can't figure out why. Am I going about it in the wrong way?
Test code:
public class MyTest{
#Test
public void testMe(){
MyIntegration.mock();
}
}
public MyIntegration{
#RegisterExtension
static WireMockExtension wiremock = WireMockExtension.newInstance(wireMockConfig().port(9000)).build();
public static void mock(){
var info = wiremock.getRuntimeInfo(); // wireMockServer is null
wiremock.stubFor(...); // NPE
}
}
JUnit Jupiter scans test classes for #RegisterExtension annotations and runs the lifecycle methods on the annotated objects, but it won't scan non-test classes, which is why the server isn't being started in your example.
You have two options:
Create a base class with the WireMockExtension instances in it, then make each test class extend this.
In your integration class, new up an instance of WireMockServer, then make sure you call the start() and stop() methods on it before/after your test cases.
My preference is usually 1) in this scenario.
I am writing app that uses various REST api endpoints with very similar properties. Only difference is in endpoint adress and payload. Headers, method and other stuff remain the same. That is why I created class to communicate with my remote host, it is called RestApiCommunicator that has method generateRequestAndCallEndpoint(List payload) that wraps payload with all required stuff needed to perform rest call.
Than, I have various classes that only call this communicator class with proper endpoint suffix an its resources.
Everything is working fine but I want to unit test all of those classes. I was trying to figure out how to do that by reading a lot of SO questions but they are rather complicated cases, my is very simple.
I am trying to figure out a proper way to unit test a class that looks like this one:
class MyRestClient {
public void useRestApi(List<MyResources> myResources) {
RestApiCommunicator restApiCommunicator = new RestApiCommunicator ("/some/endpoint");
restApiCommunicator.generateRequestAndCallEndpoint(myResources);
}
}
I want to test if communicator was created with proper enpoint adress and if generateRequestAndCallEndpoint was called exacly once with my sample payload.
Only thing that comes to my mind is that make restApiCommunicator a field, create setter for this field and mock it in Unit tests. But this seems to me as rather dirty solution and I wouldn't like to modify my code to allow tests.
Maybe you can point me in some direction where I could have this class tested using some good pattern.
(ps. If that matters - this is a Spring Boot app)
You could provide a factory for the communicator
class MyRestClient {
private RestApiCommunicatorFactory factory = ...
public void useRestApi(List<MyResources> myResources) {
factory.getCommunicator("/some/endpoint")
.generateRequestAndCallEndpoint(myResources);
}
In your unit test, you provide a mock of the factory, which returns mock communicators. The specific language for that depends on your mocking library of choice.
One way to do exactly what you ask (ie, "to test if communicator was created with proper enpoint adress and if generateRequestAndCallEndpoint was called exactly once with my sample payload") is to mock it using JMockit:
public final class MyRestClientTest {
#Tested MyRestClient restClient;
#Mocked RestApiCommunicator restApi;
#Test
public void verifyUseOfRestApi() {
List<MyResource> resources = asList(new MyResource("a"), new MyResource("b"));
restClient.useRestApi(resources);
new Verifications() {{
new RestApiCommunicator("/some/endpoint");
restApi.generateRequestAndCallEndpoint(resources); times = 1;
}};
}
}
I have simple Android application with some espresso tests.
I want to write some base class so all of my test classes will inherit its #beforeClass and #afterClass methods, but the problem is when I do it like code example below, JUnit doesn't see any tests at al. I got Empty test suite. message. What's the problem?
Code example:
public class RealmTest {
protected static Realm realm;
#BeforeClass
public static void beforeClass() {
realm = Realm.getDefaultInstance();
realm.setAutoRefresh(true);
}
#AfterClass
public static void afterClass() {
realm.close();
}
}
#RunWith(AndroidJUnit4.class)
public class MainActivityTest extends RealmTest {
#Rule
public IntentsTestRule<MainActivity> activityTestRule = new IntentsTestRule<>(MainActivity.class);
#Test
public void startedFine() {
assertNotNull(realm);
onView(withId(R.id.button)).perform(click());
intended(hasComponent(new ComponentName(getTargetContext(), EducationActivity.class)));
}
}
If I'll run all tests, tests from MainActivityTest won't run.
Thanks for your help, pls say if some additional info is needed.
Guessing: the JUnit environment is not looking for static methods. So maybe you simply drop that keyword from your base methods (guess you could keep your Realm static nonetheless; I assume you really only want one of those).
But then, another suggestion: don't use inheritance for test cases.
The point that makes test cases valuable to you is: they should quickly allow you to find and fix bugs in your production code.
But when your "setup" is hidden from your testcases - because things are not only happening in some #Before method ... but in a #Before method somewhere, in some different class ... well, that can seriously increase the time you will need to understand a failing testcase. Because: instead of just studying your test case, you find yourself digging around within test code in order to understand what exactly is happening besides the code in that failing test method itself!
Thus: be really careful to balancing "code duplication" versus "test case is easy to understand" aspects!
I have started reading the Spring in Action book.
I have no knowledge of JUnit which I think my doubt is about.
There is a code fragment where the author refers to and says that it is difficult to test:
package com.springinaction.knights;
public classDamselRescuingKnight implements Knight {
private RescueDamselQuest quest;
public DamselRescuingKnight() {
quest = new RescueDamselQuest();
}
public voidembarkOnQuest() throwsQuestException {
quest.embark();
}
}
The author says that:
It’d be terribly difficult to write a unit test for DamselRescuingKnight. In such a test, you’d like to be able to assert that the quest’s embark() method is called when the knight’s embarkOnQuest() is called. But there’s no clear way to accomplish that here. Unfortunately, DamselRescuingKnight will remain untested.
What does the author mean by this?
Why is the code difficult to test here?
My initial thought is that it is difficult to test because the "RescureDamselQuest" object is initialized in the constructor. This makes it difficult to for example insert a mock object. A mock object would help you test that the embark() method is called on the "RescueDamselQuest" object.
A better way to solve this can be to either include a parameter in the constructor (usually I prefer this method):
public DamselRescuingKnight(RescueDamselQuest quest){
this.quest = quest;
}
Or add a setter:
public void setDamselRescuingKnight(RescueDamselQuest quest){
this.quest = quest;
}
A common example I give is consider that you want to open a file, parse it, and get a data class out. Most will do something like:
Data openAndParse(String filename) {
...openFile
...parse
}
By doing it this way, the file open methodology and parse is highly coupled and difficult to test. If you have a problem in open and parse is it with the parse or the open?
By writing JUnit test, you are forced, for simplicity sake, to do something like...
BufferedReader openFile(String filename) {
...open file and return reader
}
Data parse(BufferedReader input) {
...parse and return data
}
JUnit leads us to a more cohesive solution. We write JUnit test simply by creating a string, constructing a StringReader, and then a BufferedReader. Well guess what? Very similarly we can now use parse to accept input from a variety of sources not just the file.
It's difficult to test because the quest implementation cannot be swapped out. Without byte code modification there's no trivial way to see if embark is called.
If you could set the quest implementation in a constructor or setter you could pass in an implementation that can spy on the call to embark.
One need to increase accessibility of fields and method of class to test. For example if one is testing a method which is package-private (default) then test cases which are generally in different package will not able to test this method. Therefore it is advised to to change in accessibility of fields to test the method. DamselRescuingKnight class can be tested which is not using DI by modifying the accessibility of RescueDamselQuest field from private to default. Then writing test case using mockito. Here is code for test case
#Test
public void knightShouldEmbarkOnQuest() throws QuestException {
DamselRescuingKnight knight = new DamselRescuingKnight();
RescueDamselQuest quest = mock(RescueDamselQuest.class);
knight.quest = quest;
knight.embarkOnQuest();
verify(quest, times(1)).embark();
}
And line which was changed in DamselRescuingKnight class to remove private accessibility
RescueDamselQuest quest;
I got a lot of different flows which are resuing moduls. Like this Flow1 = M1->M2->M3->M5 or Flow2 = M1->M2->M4->M6->M3->M5.
Now I want to write a testCase for each modul to shorten the time of testdevelopement and then combine those cases to test the flow. Those tests all need an initial setup, sometimes other paramters and certain informations should be carried through the flow. How can I insert them into the testmodul without hardcoding them into the model since they should be changeable for reuse.
Since testcases do not support constructors and parameterized test cases are not what I am looking for.
So not like
Running the same JUnit test case multiple time with different data
but Running differen JUnit test cases with the same source of data.
Is it possible to do that or am I on the wrong track?
If anything is unclear please ask.
I'd really appreciate help.
Greetings
Tarken
Let's see if I understand your problem correctly. You would like to define a test for M1 (testM1), a test for M2 (testM2) a test for M3 (testM3) etc. You would then like to test the combination of M1->M2->M3 by calling all of the test methods testM1, testM2, testM3 in order, but passing some arbitrary data between those methods. So testM1 gets called, and it produces some data which gets passed to testM2, which produces data which gets passed to testM3. The solution below is designed for this, but can easily be extended to include classes.
There are two ways of doing this. The easiest is to define a #Rule in your classes which gets the context stored in a static field in the Suite class and updates it. If you extend ExternalResource, you can do something like:
private Context context;
#Rule
public ExternalResource resource= new ExternalResource() {
#Override
protected void before() throws Throwable {
// get context from Suite class
context = MySuite.getContext();
};
#Override
protected void after() {
// put context into Suite class
MySuite.setContext(context);
};
};
Your methods would then use that context as normal. This would work in most cases, but creates a dependance from the test to a particular MySuite class.
The more complex option
You can do this using a custom #Suite class with a customer Runner. My answer to How to define JUnit method rule in a suite? shows how to execute custom code before and after a particular method (in that case one with a #depcrecated annotation).
You would need to do something similar. So your Suite would create the context for the test, and before executing a particular test method, the runner retrieves the context from the suite, calls a setter in the test class. The test method uses that context, returns and the runner retrieves the context from the test class and updates the suite class. The obvious place to store the context would be the suite, since the test classes themselves are created each time. I think it's too much work to try and pass the context in as a parameter, you'd have to change a lot more code.
So in your Runner, you would have something like
public class MyRunner extends BlockJUnit4ClassRunner {
private MySuite suite;
public MyRunner(Class<?> klass, MySuite suite) throws InitializationError {
super(klass);
this.suite = suite;
}
#Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
Description description= describeChild(method);
if (method.getAnnotation(Ignore.class) != null) {
notifier.fireTestIgnored(description);
} else {
// call suite.getContext()
// call setContext() in class
runLeaf(methodBlock(method), description, notifier);
// call getContext() in class
// call suite.setContext()
}
}
}
It is possible to override the beforeclass behaviour as well.
Use BeforeClass.