1

I would like to be able to mock a class used by a webapp in a JUnit test running embedded Tomcat.

public interface Foo {
    void bar();
}

@RunWith(JMockit.class)
public class IntegrationTest {

    @Test
    public void mockingFoo(@Capturing final Foo foo)
            throws ServletException, LifecycleException {

        new Expectations() {{
            foo.bar(); result = new RuntimeException();
        }};

        final Tomcat tomcat = new Tomcat();

        // MyApp will invoke a Foo instance
        tomcat.addWebapp("/MyApp", "/path/to/MyApp.war");

        tomcat.start();

        /* 
        invoke the webapp (via Selenium, for example)
        The call to Foo::bar in the webapp should throw the runtime exception 
        */

        tomcat.stop();
    }
}

What can be done so that the Foo instances within the webapp are mocked via JMockit?

UPDATE - 20150821

I don't yet know the answer to my question. However, I managed to mock classes in a webapp running within Jetty.

Community
  • 1
  • 1
beluchin
  • 12,047
  • 4
  • 24
  • 35
  • If you are going to write a functional web UI test (using HTMLUnit or Selenium WebDriver), why mock anything at all? Such tests are end-to-end; normally, they access external resources like databases, and even commit transactions, so what would mocking be used for? – Rogério May 18 '15 at 16:41
  • I want to mock the business layer. It has already been tested. I want to do an integration(?) test of the webapp layer. That is, I want to end up with multiple sets of tests: business layer tests (isolated from any technology stack) and integration tests for whatever technology adapters I need to surround my business layer with. – beluchin May 18 '15 at 19:35
  • Hmm, yes, it's a valid testing strategy, but I can see some problems: 1) you won't have real acceptance/functional tests (since no single test exercises all the application code involved in a given use case scenario); 2) the effort to create and run both test suites will be greater than it would be for a single test suite with the same amount of code coverage. From experience, I know that 1) certain bugs can only (or are much easier to) be detected through real end-to-end tests; and 2) web UI tests (in particular using WebDriver) are quite challenging to *run* (more than to *create* them). – Rogério May 19 '15 at 15:04
  • (continuing) My preferred approach (using it in a Java EE 7 web app) is to write a single suite of integration tests for the application, domain, and infrastructure layers (using DDD), while leaving the UI layer (JSF ".xhtml" files) as devoid of logic as possible; I don't use tools like HTMLUnit or WebDriver because of the pain in running such tests; visual inspection of the UI is more effective anyway, even if it means some of the application code is not covered by automated tests. – Rogério May 19 '15 at 15:10
  • I appreciate the approach of the single test suite. However, even when you have a single test suite for the entire app, you are likely to need to introduce mocks somewhere - particularly for a data source you don't control. Having said that, I prefer to have a set of tests for each layer independently so that 1. it is easier to track issues given the reduced amount of code involved 2. I find it easier to recreate error conditions. – beluchin May 19 '15 at 19:30

0 Answers0