How to make xUnit fail if no Assert executed? - xunit

Basically I need to make xUnit fail by default.
So this fails:
[Fact]
public void Test()
{
}

Related

How can I run my grails-5 app's cucumber tests as part of ./gradlew check?

I am writing a Grails-5 and I am using cucumber for BDD. I've followed the tutorial at: https://www.baeldung.com/java-cucumber-gradle
I can run my unit tests using:
$ ./gradlew check
And I can run my cucumber BDD tests by starting the server in one shell:
$ ./gradlew server:bootRun
And invoking the tests in another:
$ ./gradlew cucumberCli
Is it possible to configure build.gradle in such a way as to have ./gradlew check run the unit tests, then start the server, then run the cucumber tests, and finally bring the server back down?
If at all possible, it would be even better if the cucumber infrastructure could start and stop the server between each test. That way each test would start in a known state.
I managed to get this working by adding #Before and #After steps to my StepDefinitions.groovy file:
def serverProcess
private String getBaseUrl() {
return "http://localhost/"
}
#Before
public void startServer() {
try {
serverProcess=Runtime.getRuntime().exec("../gradlew bootRun")
} catch (IOException e) {
e.printStackTrace()
}
def done = false
while(!done) {
try {
done = new URL(getBaseUrl()).openConnection().getResponseCode() == 200
} catch(Exception e) {
Thread.sleep(500)
}
}
}
#After
public void stopServer() {
serverProcess.destroy()
}

Spring Boot Cucumber Java 8 Testing ApplicationOnReady Event

I have a reporting application that generates a report on ApplicationReadyEvent. I am trying to write cucumber tests for it but as the application event is fired even before my feature is executed , i am not sure what is the right way to test it. Can i control the event during testing ?
#EventListener(ApplicationReadyEvent.class)
private void generateAccuracyAnalysisReport() throws IOException
{
//some Logic
}
Cucumber Classes :
#SpringBootTest
#CucumberContextConfiguration
#ActiveProfiles("junit")
public class CucumberConfiguration
{
}
#RunWith(Cucumber.class)
#CucumberOptions(plugin = "pretty", features = "src/test/resources/cucumber/features")
public class CucumberFullIntegrationTest
{
}
Step Definition:
public class ReportStepDefs implements En {
public ReportStepDefs() {
When("^System sends an application event to generate report$", () -> {
});
Then("^Report should be generated successfully\\.$", () -> {
});
}
}
If your Cucumber tests involve Spring life-cycle you can not use cucumber-spring. Rather you have to use something like Springs ApplicationContextRunner to, configure, run and verify something about your application as part of each scenario.
// Given
ApplicationContextRunner contextRunner = new ApplicationContextRunner();
// When
contextRunner.withConfiguration(AutoConfigurations.of(...);
// Then
contextRunner.run(context -> assertThat(context).... /* something */ );
// Or assert something external to the application context.
Though it sounds like your application is doing something once and then exits. If so you should be using the CommandLineRunner instead of ApplicationReadyEvent in a web application. This is testable with cucumber-spring.
#RequiredArsConstructor
public class StepDefinitions {
final MyCommandLineRunner commandLineRunner;
#When(....)
public void something() {
commandLineRunner.run("input.txt", "input2.txt");
}
#Then(....)
public void assertSomething() {
// check if report was generated
}
}

How to write script in gradle that execute particular methods?

I am writing a gradle script that runs all tests before making a build.
test {
filter {
includeTestsMatching "*TestAll*"
includeTestsMatching "*ExtensionValidatorTest*"
........
}
}
I have three tests of different versions(v1,v2,v3).
TestAll.java
package .....v1;//v2 for version 2 and v3 for version 3
#RunWith(Suite.class)
#Suite.SuiteClasses({
A.class,
B.class,
......
})
public class TestAll {
#BeforeClass
public static void setUp() {//connection to database
........
}
#AfterClass
public static void tearDown() {//close database connection
........
}
}
When I run gradle test connection to database is broken after execution of a particular TestAll. I do not want to change the TestAll files of any version as they can be run and tested independently. How can I make gradle run only setUp once(of any version)which establishes connection, then run all the TestAll method in v1,v2 and v3 and finally teardown(of any version) which terminates database connection.
Gradle won't help you with this. There are following methods in Gradle DSL:
test {
beforeSuite{...}
afterSuite{...}
}
However, they execute outside of the test runtime scope and intended for logging. You only can achieve this using a testing framework.
TestNG provides a simple solution - #BeforeSuite and #AfterSuite annotations, that are actually run once before and after the entire suite.
Unfortunately, JUnit doesn't have a built-in solution for that, since test isolation is its core concept. Nevertheless, you still can make your own. You need to encapsulate database-related API into a singleton class:
public class DbContainer() {
private static DbContainer container;
private DbContaner() {}
public DbContainer getInstance() {
if (container == null) {
container = new DbContainer()
}
return container;
}
public void openConnection() {
// ...
}
public void closeConnection() {
// ...
}
// here is your database API methods
}
Then you can share this instance between test methods and classes using #ClassRule annotation:
#ClassRule
public static DbContainer db = DbContainer.getInstance();
#Test
public void someTest() {
db.query(...)
}
Note: provided solution is not thread-safe and doesn't suit the parallel execution. Some additional effort is required to achieve it.

Using Mockito with TestNG

I took a working test written for JUnit using Mockito and tried to adapt it to work with TestNG but oddly using TestNG only one test will work.
I think it is somehow related to the resetting of the mocks but I have played around with trying to call Mockito.reset and using BeforeMethod and BeforeClass and different combinations but still can only get one test to pass.
What I need to do to get the test to work?
#BeforeClass
public void setUp() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(calculatorController).build();
}
#AfterMethod
public void reset() {
Mockito.reset(calculatorService);
}
#Test
public void addFunctionTest() throws Exception {
Assert.assertNotNull(calculatorController);
Result expectedResult = new Result();
expectedResult.setResult(10);
when(calculatorService.add(anyInt(), anyInt())).thenReturn(expectedResult);
mockMvc.perform(get("/calculator/add").accept(MediaType.APPLICATION_JSON_VALUE)
.param("val1", "100")
.param("val2", "100"))
.andExpect(content().contentType("application/json"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.result", equalTo(10)));
verify(calculatorService, times(1)).add(anyInt(), anyInt());
}
#Test
public void subtractFunctionTest() throws Exception {
Assert.assertNotNull(calculatorController);
Result expectedResult = new Result();
expectedResult.setResult(90);
when(calculatorService.subtract(anyInt(), anyInt())).thenReturn(expectedResult);
mockMvc.perform(get("/calculator/subtract").accept(MediaType.APPLICATION_JSON_VALUE)
.param("val1", "100")
.param("val2", "10"))
.andExpect(content().contentType("application/json"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.result", equalTo(90)));
verify(calculatorService, times(1)).subtract(anyInt(), anyInt());
}
The second test always seems to fail on assertions that either content type is not set or the expected result is wrong.
It seems like the response for the first test is somehow being evaluated in the second test and so is obviously wrong!
I know the controller and service work as expected and the exact same tests running with jUnit actually work ok.
I have managed to get the tests to perform properly only when I do the following:
#BeforeGroups("subtract")
public void reset() {
Mockito.reset(calculatorService);
mockMvc = MockMvcBuilders.standaloneSetup(calculatorController).build();
}
#Test(groups = "subtract")
public void subtractFunctionTest() throws Exception {
System.out.println("***** IN METHOD *****");
Assert.assertNotNull(calculatorController);
Result expectedResult = new Result();
expectedResult.setResult(90);
when(calculatorService.subtract(anyInt(), anyInt())).thenReturn(expectedResult);
//Perform HTTP Get for the homepage
mockMvc.perform(get("/calculator/subtract").accept(MediaType.APPLICATION_JSON_VALUE)
.param("val1", "100")
.param("val2", "10"))
.andExpect(content().contentType("application/json"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.result", equalTo(90)));
//Verify that the service method was only called one time
verify(calculatorService, times(1)).subtract(anyInt(), anyInt());
}
This means I need to add one of these reset methods for each test method though and I then need a group per test method which doesnt seem correct.
There is a difference in the behaviour of these frameworks:
JUnit creates a new instance of class for every of its test methods. This means that the fields are not shared between tests.
But TestNG creates only one object and thus the state in fields is shared between to #Tests
For Mockito you need to init mocks before every test method so that the state is not shared between two #Tests in TestNG:
#BeforeMethod
public void init() {
MockitoAnnotations.initMocks(this);
}
For JUnit it works out of box because 2nd #Test has its own fields and its own mocks.
I'm not sure, if this answer fits to the questioners problem, because the mocks are not listed. But I'd like to re-state one comment from andy in the accepted answer, which helped me out on the same problem. Here are some more details and an example:
public class B {
private A a;
B (A a) {
this.a = a
}
// ...
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class MyTest {
#Mock
A a;
#InjectMocks
B B;
#BeforeMethod
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
void test1() {
// ...
// b.toString();
// b.getA().toString();
// a.toString();
}
#Test
void test2() {
// ...
// b.toString();
// b.getA().toString();
// a.toString();
}
#AfterMethod
public void reset()
{
// Solution:
b = null;
}
}
Mockitos MockitoAnnotations.initMocks(this) only re-initializes mocks, as Mockito.reset(a) only resets mocks. The problem is the class under test, which is annotated with #InjectMocks. This class, here named B, is not initialized again. It is initialized for the first test with a mock of A, the mock of A is re-initialized but B still contains the first version of A.
The solution is to reset the class under test manually with b = null at any plausible place (#AfterMethod or before initMocks). Then Mockito also re-inizialized the class under test B.
You can also use MockitoTestNGListener it is similar to JUnit MockitoJUnitRunner or MockitoExtension.
Example of code:
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.testng.MockitoTestNGListener;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import java.util.Map;
#Listeners(MockitoTestNGListener.class)
public class MyTest {
#Mock
Map map;
#InjectMocks
SomeType someType;
#Test
void test() {
// ...
}
}

Is there a concept of test suites in Gradle/Spock land?

Groovy/Gradle project here that uses Spock for unit testing.
Does Spock and/or Gradle support test suites or named sets of tests? For reasons outside the scope of this question, there are certain Spock tests (Specifications) that the CI server just can't run.
So it would be great to divide all my app's Spock tests into two groups:
"ci-tests"; and
"local-only-tests"
And then perhaps we could invoke them via:
./gradlew test --suite ci-tests
etc. Is this possible? If so, what does the setup/config look like?
You can annotate the tests that should not run in your CI server with the Spock annotation #IgnoreIf( ).
See the documentation here: https://spockframework.github.io/spock/docs/1.0/extensions.html#_ignoreif
All you need to do is let the CI server set an environment variable, and exclude the test class if that variable is set.
Spock even have properties inside the closure to make it easy:
#IgnoreIf({ sys.isCiServer })
I would set up a submodule my-app-ci-test, with the following in build.gradle:
test {
enabled = false
}
task functionalTest(type: Test) {
}
Then you place your tests in src/test/groovy and run ./gradlew functionalTest.
Alternatively, you could include them in the same module and configure the test and functionalTest tasks with includes / excludes
test {
exclude '**/*FunctionalTest.groovy'
}
task functionalTest(type: Test) {
include '**/*FunctionalTest.groovy'
}
If you use Junit test-runner for Spock tests, you may use #Category annotation. Example by article and official documentation:
public interface FastTests {
}
public interface SlowTests {
}
public interface SmokeTests
}
public static class A {
#Test
public void a() {
fail();
}
#Category(SlowTests.class)
#Test
public void b() {
}
#Category({FastTests.class, SmokeTests.class})
#Test
public void c() {
}
}
#Category({SlowTests.class, FastTests.class})
public static class B {
#Test
public void d() {
}
}
test {
useJUnit {
includeCategories 'package.FastTests'
}
testLogging {
showStandardStreams = true
}
}
You can use the following SpockConfiguration.groovy to allow passing include/exclude via system properties
runner {
exclude {
System.properties['spock.exclude.annotations']
?.split(',')
*.trim()
?.each {
try {
annotation Class.forName(it)
println "Excluding ${it}"
} catch (ClassNotFoundException e) {
println "Can't load ${it}: ${e.message}"
}
}
}
include {
System.properties['spock.include.annotations']
?.split(',')
*.trim()
?.each {
try {
annotation Class.forName(it)
println "Including ${it}"
} catch (ClassNotFoundException e) {
println "Can't load ${it}: ${e.message}"
}
}
}
}

Resources