Giter Site home page Giter Site logo

rule-them-all's Introduction

Rule Them All!

A set of JUnit rules to ease testing setup.

Note dependencies are optional so you need to bring the ones the rule you use needs.

System properties

There is already some rules to set system properties like http://www.stefan-birkner.de/system-rules/ but it doesn’t support placeholder.

The idea here is to declare system properties through annotations:

@Rule
public final PlaceHoldableSystemProperties unit = new PlaceHoldableSystemProperties();

@Test
@SystemProperties({
  @SystemProperty(key = "my.key", value = "my value"),
  @SystemProperty(key = "my.other.key", value = "my other value"),
  @SystemProperty(key = "other.value.copy", value = "${my.other.key}")
})
public void myTest() throws IOException {
    // ...
}

@SystemProperty can be on method and class, both will be merged.

${} uses other system properties and you can also use #{} to match a field. This last case is very useful with arquillian:

@RunAsClient // other you don't have @ArquillianResource URL
@RunWith(Arquillian.class)
public class MyTest {

  // @Deployment etc...

  @Rule // DON'T FORGET TO PASS THIS AS PARAMETER
  public final PlaceHoldableSystemProperties unit = new PlaceHoldableSystemProperties(this);

  @ArquillianResource
  private URL url;

  @Test
  @SystemProperties({
    @SystemProperty(key = "base.url", value = "#{url}")
  })
  public void myTest() throws IOException {
    // ...
  }
}

Ftp

Another rule relies on MockFtpServer library to create a ftp server through a rule.

Here too you define what is your ftp server through annotations. You can define the port/user/password/root directory to use through @FtpServer annotation but files too:

@Rule
public final FtpServerRule unit = new FtpServerRule(this);

@Test
@FtpServer(
  files = {
    @FtpFile(name = "foo.txt", content = "bar.txt")
  },
  user = "test", password = "pwd"
)
public void myTest() throws IOException {
    assertNull(stayNull);
    assertNotNull(fs);
    assertNotNull(server);
    assertTrue(server.getServerControlPort() > 0);
    assertEquals(Integer.toString(server.getServerControlPort()), System.getProperty(FtpServer.FTP_PORT));
    oldServer = server;
}

Here method OR class annotation is taken into account.

By default port is random and can be retrieved through the FtpServer.FTP_PORT system property.

If you passed to the rule the test instance (or another class) you can use @UnitInject to get the FTP FileSystem to let the FTP files be dynamic or directly the FakeFtpServer.

Sftp

This rules allows to mock a very simple SFTP server.

It is mainly inspired from FTP one.

@Rule
public final FtpServerRule unit = new FtpServerRule(this);

@Test
@SftpServer(@SftpFile(name = "/dummy/foo.txt", content = "Awesome"))
public void myTest() throws IOException {
    assertNotNull(server);
    assertTrue(server.getPort() > 0);
    assertEquals(Integer.toString(server.getPort()), System.getProperty(SftpServer.PORT));
    oldServer = server;

    // client
    final JSch jSch = new JSch();
    final Session session = jSch.getSession("test", "localhost", server.getPort());
    session.setPassword("testpwd");
    session.setConfig(new Properties() {{ put("StrictHostKeyChecking", "no"); }});
    session.connect();
    final ChannelSftp channel = ChannelSftp.class.cast(session.openChannel("sftp"));
    channel.connect();
    final ByteArrayOutputStream dst = new ByteArrayOutputStream();
    channel.get("/dummy/foo.txt", dst);
    assertEquals("Awesome", new String(dst.toByteArray()));
}

Note that SftpServer.PORT system property is set to the server port is you need to use it with PlaceHoldableSystemProperties and that you can add later files on the server using the rule addFile method.

Spring rule

spring-test brings a nice runner for JUnit but its lifecycle doesn’t work that well with rules (in particular if you rely on system properties). To solve it the runner logic was included in SpringRule:

// @DirtiesContext(...)
@ContextConfiguration("classpath:appCtx.xml")
public class TestSpringRule {
	@Rule
	public final SpringRule rule = new SpringRule(this);

	@Autowired
	@Qualifier("foo")
	private String fooSpringBean;

	@Test
	public void run() {
		assertEquals("test", fooSpringBean);
	}
}

Combine them

Since Java 7 you have no more guarantee about fields order in a class. So when you declare rules you don’t know which one will be called first.

If you use the spring+ftp+system property rules it can be an issue. Let say you use a system property as place holder in your spring context and that it is the ftp url to use. In this case you want to:

  • start the ftp server (and implicitely set the ftp port in system property)

  • set the spring placeholder key in a system property using ftp port system property

  • start spring and reuse the url system property

To sort rules JUnit includes now RuleChain.

Here a sample spring bean which could be used in this context:

<bean id="port" class="java.lang.Integer">
  <constructor-arg value="${ftp.port}" />
</bean>

And here is the test class:

@SystemProperties(@SystemProperty(key = "ftp.port", value = "${" + FtpServer.FTP_PORT + '}'))
@ContextConfiguration("classpath:ftp.xml")
public class TestCombineThemAll {
    @Rule
    public RuleChain chain = RuleChain.outerRule(new FtpServerRule(this))
            .around(new PlaceHoldableSystemProperties())
            .around(new SpringRule(this));

    @Autowired
    @Qualifier("port")
    private int port;

    @Test
    @FtpServer // empty server for the demo
    public void run() {
        assertTrue(port > 0);
    }
}

Hazelcast rule

Simply starts a hazelcast instance either from provided config or from hazelcast.xml:

public class HazelcastRuleTest {
	@Rule
	public final HazelcastRule rule = new HazelcastRule();

	@Test
	public void run() {
		assertNotNull(rule.getInstance());
		assertTrue(rule.getInstance().getLifecycleService().isRunning());
	}
}

BaseDir rule

Simple set a system property with current directory, useful to use as placeholder in combination with PlaceHoldableSystemProperties.

Basic usage:

public class BaseDirRuleTest {
	@Rule
	public final BaseDirRule rule = new BaseDirRule();

	@Test
	public void ensureSystemPropIsAvailable() {
		assertNotNull(System.getProperty(rule.getPropName()));
		assertNotNull(System.getProperty("project.basedir"));
	}
}

And with PlaceHoldableSystemProperties:

@SystemProperties(@SystemProperty(key = "config.path", value = "${project.basedir}/src/test/configuration"))
public class BaseDirRuleTest {
	@Rule
    public RuleChain chain = RuleChain.outerRule(new BaseDirRule())
                .around(new PlaceHoldableSystemProperties());

    // ...
}

PhantomJS rule

Needed dependencies:

<dependency>
  <groupId>com.github.detro</groupId>
  <artifactId>phantomjsdriver</artifactId>
  <version>1.2.0</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>org.jboss.arquillian.extension</groupId>
  <artifactId>arquillian-phantom-binary</artifactId>
  <version>1.9.7</version>
  <classifier>linux-64</classifier> <!-- adapt to your case -->
  <scope>test</scope>
</dependency>

Usage:

public class PhantomJsRuleTest {
    @Rule
    public final PhantomJsRule rule = new PhantomJsRule();

    @Test
    public void run() throws IOException {
        rule.getDriver().get("http://localhost:" + port + "/test");
        String page = rule.getDriver().getPageSource();
    }
}

File

com.github.rmannibucau.rules.api.file.FileRule is intended to simply the creation of file and the validation of file output after the test.

Usage:

public class PhantomJsRuleTest {
    @Rule
    public final FileRule rule = new FileRule();

    @Test
    @CreateFile(path = "target/in/file.txt", content = "content")
    @ExpectedOutput(path = "target/out/file-modified.txt", content = "content 2")
    public void run() {
        // do something with file.txt
    }
}

rule-them-all's People

Contributors

rmannibucau avatar

Stargazers

 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.