views:

160

answers:

3

All,

I'm using Cucumber for acceptance testing a Ruby command line utility. This utility pulls data in from a webservice.

I understand Cucumber is for acceptance testing and tests the whole stack but I still need to provide consistant replies from the webservice.

Should I mock the webservice? If yes, how? What's the best approach here?

Cheers, Gordon

+1  A: 

I am not very familiar with Ruby or Cucumber, so I can only give you a very general answer related to your problem, and it actually has more questions than answers.

  • How reliable are the web services? If they are down a lot it will make your tests fail from time to time and there is nothing more annoying than chasing down the reason for a failing test only to realize it was that time of the month again.
  • Can your web services take the pounding from tests? If you have several developers running these tests very often and your web services are on a partner company's server, they might not like the fact that you are testing against them.
  • Do you trust their output? For me the biggest reason not to mock a dependency is if I don't know what sort of data I am exactly going to get from the service. If I am using services that are well documented and easily understandable I usually don't mock them, but if they are not entirely clear or they change often I do recommend testing against them.
  • How hard is it to mock the dependency? Replacing dependencies is not always easy, especially if adding test code afterwards. Luckily in dynamic languages it is usually a lot easier than lets say Java. I would still consider how much work does it take to build a mock service that responds with the answers you are really wanting.
  • How much of a speed benefit I gain from mocking? Integration tests are slow, mocking a web service dependency is gonna make your test run faster, how much faster? I don't know but it probably does matter.

Those are just a few points, but at least the last three I always consider before choosing to mock or not to mock.

ponzao
Thanks for the guidance ponzao. Very useful for deciding whether to mock or not. But It looks like someone has already done the hard work for me. See my own answer about FakeWeb for the details.
Gordon McAllister
+1  A: 

So after a bit of thinking! Then a bit of googling I found FakeWeb. Does exactly what I needed!

Check out Dr Nic's slides - especially slide 17.

And it was easy - in under 2 hours I've managed to set it up, rewrite my tests, get everything passing and check it all back in to git hub!!

HTH others!

Gordon McAllister
Excellent that you got it working! I'll definitely have to check FakeWeb out.
ponzao
A: 

Mock of the Webservice

I would write a wrapper around the calls to the webservice in the application.
Example in Pseudo Code

CallWebService (action, options,...) {
    // Code for connectiong to Webservice
}

Then you just mock of that function just you would like any other function

CallWebService (action, options,...) {
    return true;
}

This way you can mock of the webservice without bothering about it being a webservice or a database connection or whatever. And you can have it return true or whatever.

Test how your code handles responses from the Webservice

To take this idea one step further and make your tests even more powerful you could use some kind of test parameters or environment parameters to control what happens in the mocked off webservice method. Then you can successfully test how your codes handels different responses from the web services.
Again in pseudo-code:

CallWebService (action, options,...) {
    if TEST_WEBSERVICE_PARAMETER == CORRUPT_XML
        return "<xml><</xmy>";
    else if TEST_WEBSERVICE_PARAMETER == TIME_OUT
        return wait(5000);
    else if TEST_WEBSERVICE_PARAMETER == EMPTY_XML
        return "";
    else if TEST_WEBSERVICE_PARAMETER == REALLY_LONG_XML_RESPONSE
        return generate_xml_response(1000000);
}

And tests to match:

should_raise_error_on_empty_xml_response_from_webservice() {
    TEST_WEBSERVICE_PARAMETER = EMPTY_XML;
    CallWebService(action, option, ...);
    assert_error_was_raised(EMPTY_RESPONSE_FROM_WEBSERVICE);
    assert_written_in_log(EMPTY_RESPONSE_LOG_MESSAGE);
}
...

And so on, you get the point.
Please note that even though all my examples are Negative test cases this could of course be used to test Positive test cases also.

Do note that this is a copy of an answer i made to a similar questions: http://stackoverflow.com/questions/3492419/mockup-webservice-for-iphone

Good luck

Jonas Söderström