I've got some code I'm deploying to Google App Engine - Java (GAE/J) that makes use of the URLFetchService. I'd like to use JUnit to test this code. Per the testing documentation, it appears I should have a test that uses their LocalURLFetchServiceTestConfig class ROUGHLY as follows:
public class MyRemoteServiceTests {
private static final LocalURLFetchServiceTestConfig urlConfig = new LocalURLFetchServiceTestConfig();
private static final LocalServiceTestHelper helper =
new LocalServiceTestHelper(urlConfig);
#Before
public void setUp() throws Exception {
service = new SampleService();
helper.setUp();
}
#After
public void tearDown() throws Exception {
service = null;
helper.tearDown();
}
#Test
public void testThatCallsCodeThatUsesUrlFetch() {
Object data = service.getRemoteDataUsingUrlFetch("foo", "bar");
Assert.assertNotNull(data);
}
}
I'm finding that this test continues to fail despite using the "helper" as suggested in the GAE/J documentation on testing: "The API package 'urlfetch' or call 'Fetch()' was not found.".
I was assuming that using the "helper" would somehow setup the GAE environment such that when I call URLFetchServiceFactory.getURLFetchService() from within my getRemoteDataUsingUrlFetch method, the interface returned would be an instance of LocalURLFetchService that would just "work" but that seems NOT to be the case.
How can I test this code?
Am I missing something? (I'm pretty new to GAE...)
Do I have to refactor my getRemoteDataUsingUrlFetch so that it doesn't use URLFetchServiceFactory.getURLFetchService() because that makes it untestable locally??? (That sounds like it would really suck...)
Any help/suggestions much appreciated!
Actually, it turns out my problem was failure to include two additional jars that ARE mentioned on the Local Unit Testing page of the documentation. RTM FTW!
appengine-local-runtime.jar
appengine-api-stubs.jar
afaik, the LocalURLFetchService doesn't configure the GAE like you expect. It is more of a way to fetch URL from the local dev and then process the contents however. (Similarly even the LocalDatastoreService and LocalMemcacheService operate on isolated spaces within the test environment)
One way to test your code is to refactor the getRemoteDataUsingUrlFetch() to take maybe the contents of the Url response. somewhat like,
URLFetchResponse resp = LocalURLFetchService.fetch(status, request)
getRemoteDataUsingUrlFetch(foo, bar, resp)
Related
I want to mock my grpc client to ensure that it is resilient to failure by throwing an new StatusRuntimeException(Status.UNAVAILABLE) (This is the exception that is thrown when java.net.ConnectException: Connection refused is thrown to the grpc client). However, the generated class is final, so mock will not work.
How do I get BlahServiceBlockingStub to throw new StatusRuntimeException(Status.UNAVAILABLE) without having to refactor my code to create a wrapper class around BlahServiceBlockingStub?
This is what I have tried (where BlahServiceBlockingStub was generated by grpc):
#Test
public void test() {
BlahServiceBlockingStub blahServiceBlockingStub = mock(BlahServiceBlockingStub.class);
when(blahServiceBlockingStub.blah(any())).thenThrow(new StatusRuntimeException(Status.UNAVAILABLE));
blahServiceBlockingStub.blah(null);
}
Unfortunately I get the below exception as expected:
org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class BlahServiceGrpc$BlahServiceBlockingStub
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types
at MyTestClass.test(MyTestClass.java:655)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
.
.
.
Because I tried mocking the final class generated by grpc:
public static final class BlahServiceBlockingStub extends io.grpc.stub.AbstractStub<BlahServiceBlockingStub> {
private BlahServiceBlockingStub(io.grpc.Channel channel) {
super(channel);
}
Do not mock the client stub, or any other final class/method. The gRPC team may go out of their way to break your usage of such mocks, as they are extremely brittle and can produce "impossible" results.
Mock the service, not the client stub. When combined with the in-process transport it produces fast, reliable tests. This is the same approach as demonstrated in the grpc-java hello world example.
#Rule
public final GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();
#Test
public void test() {
// This can be a mock, but is easier here as a fake implementation
BlahServiceImplBase serviceImpl = new BlahServiceImplBase() {
#Override public void blah(Request req, StreamObserver<Response> resp) {
resp.onError(new StatusRuntimeException(Status.UNAVAILABLE));
}
};
// Note that the channel and server can be created in any order
grpcCleanup.register(InProcessServerBuilder.forName("mytest")
.directExecutor().addService(serviceImpl).build().start());
ManagedChannel chan = grpcCleanup.register(
InProcessChannelBuilder.forName("mytest").directExecutor().build();
BlahServiceBlockingStub blahServiceBlockingStub
= BlahServiceGrpc.newBlockingStub();
blahServiceBlockingStub.blah(null);
}
When doing multiple tests, you can hoist the server, channel, and stub creation into fields or #Before, out of the individual tests. When doing that it can be convenient to use MutableHandlerRegistry as a fallbackHandlerRegistry() on the server. That allows you to register services after the server is started. See the route guide example for a fuller example of that approach.
You have a few options:
NOT RECOMMENDED: Use Mockito v2 to mock final classes and methods.
NOT RECOMMENDED: Use powermock to mocks final classes and methods.
Recommended: (as already mentioned by Eric in his answer) Use the gRPC Java test framework like GrpcCleanupRule and InProcessServerBuilder. See HelloWorldClientTest for an example.
Recommended: Do over-the-wire gRPC API mocking/simulation. Use a third-party tool that will create over-the-wire API mocks/simulators for your API. For example, Traffic Parrot.
Note why mocking final, in this case, might be a bad idea:
Mocking final classes or methods might be a bad idea, depending on the case. The devil is in the details. In your situation, you are creating a mock of the generated code, so you are assuming how that generated code will behave in the future. gRPC and Protobuf are still rapidly evolving, so it might be risky to make those assumptions, as they might change and you won't notice because you do not check your mocks against the generated code. Hence, it's not a good idea to mock the generated code unless you really have to.
How to mock final classes/methods with mockito:
add dependency Mockito Inline
create file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
with one line: mock-maker-inline
And now you can mock final methods and classes.
Mockito docs about mocking
I ended up with an ugly workaround.
I created a new method and a spy() on the class that has a reference to BlahServiceBlockingStub.
The resulting code ended up looking like:
#Test
public void test() {
MyClass myClass = spy(myClass);
doThrow(new StatusRuntimeException(Status.UNAVAILABLE)).when(myClass).newMethod(any());
// changed to call myClass.newMethod() instead of blahServiceBlockingStub.blah
myClass.myExistingMethod();
}
Is it even possible to bypass certain exceptions in mockito? This sounds crazy. You want to catch expected exceptions in the unit testing I assume. However I decided to give a try asking this question. Here is my scenario hope I could improve my understanding on mockito and general unit test principals via this.
I have to build a simple unit test for a particular class Foo in an enterprise web application using mockito unit test framework.
This Foo class requires ldap and database connections however due to a reason, I can not use development environment specific ldap and database in the unit test.
I just need to test part accessing ldap so that I decided to use unboundid in memory ldap which allows to create light weight directory at run time and remove it from memory after testing is done.
My question is during the instantiation of Foo class via #InjectedMocks annotation, it triggers chain reaction of calling many other classes and their methods. It threw many exceptions which I expected.
I am trying to find a way to somehow ignore some specific exceptions such as loading/reading environment specific properties files or database access and etc.
For my goal, I don't need reading prop files nor database access.
I read upon ExpectedException junit provides which is subset of mockito if I am not mistaken however I don't think its aim aligns with my intention of bypassing some of the exceptions. I could be wrong on this.
All I want to accomplish is:
Instantiate Foo class
Call one of its methods that would read a list of group from In memory ldap
Verify returned data
Here is water downed version of test class:
#RunWith(MockitoJUnitRunner.class)
public class FooTest {
private static InMemoryDirectoryServer ldapServer;
private static Integer ldapPort = xxxxx;
#InjectedMocks
Foo footester = Foo.getInstance();
#BeforeClass
public static void setUpBeforeClass() {
try {
// execute instantiate in memory ldap..
} catch (Exception e) {
// do print out
}
}
#Test
public void testLdap() {
// before it reaches here exceptions were thrown
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
// do tear down execution
}
}
You can catch an exception like this:
#Test(expected = YourExceptionHere.class)
public void testSomething()
{
foo(FOO_VALUE);
}
I am trying to setup TestNG so that it gives me new instances of my class variable for each test (basically like JUnit). I need this as I intend to parallelize my tests at the method level. I have been experimenting with both standalone Guice and the built in Guice functionality that TestNG provides to try to accomplish this but I have had no luck. I know that I can use ThreadLocal, but calling .get() for every variable in the test is pretty unappealing. I am weary of using GuiceBerry as it does not really have a lot of updates/activity and it's last release is not even acquirable via Maven. I am pretty set on TestNG as for all the inconvenience this is causing me it still does a lot of great things. I am open to things other tools though to accomplish my goal. Basically I want things setup so the below tests would work consistently. Any help would be greatly appreciated.
// just has a variable thats a class called child with a simple string variable
// with a value of "original
Parent p;
#Test
public void sometest1(){
p.child.value = "Altered";
Assert.assertTrue(p.child.value.equals("Altered"));
}
#Test
public void sometest2(){
Assert.assertTrue(p.child.value.equals("original"));
}
TestNG doesn't create a new instance for each test. If you want such a behavior than I recommend creating separate test classes. e.g.:
public class SomeTest1 {
Parent p;
#Test
public void something(){
p.child.value = "Altered";
Assert.assertTrue(p.child.value.equals("Altered"));
}
}
public class SomeTest2 {
Parent p;
#Test
public void something(){
Assert.assertTrue(p.child.value.equals("original"));
}
}
Note that TestNG can run JUnit 3 and JUnit 4 tests (you might maintain a mixed suite depending on the style you want to use in a given test class).
I am fairly new to Java so forgive me if this is a silly question, but believe me when I say I really cannot find a solid answer.
This is what I'm working with:
So I'm testing a program, and the easiest way to keep it maintained and updated is to create my own library of "buttons". Everything in the library are small functions like "enterValidCredentials" and "clickLoginButton".
So let's take a look at my test cases. In a perfect world I'd be able to just:
public class progressCheck {
public static void main(String[] args) {
WebDriver driver = new FirefoxDriver();
driver.get("http://mail.google.com/");
enterValidCredentials;
clickLoginButton;
}
}
enterValidCredentials and clickLoginButton exist in my library of classes. I know very well that that's not going to work as written above. What, literally, is the correct way to do this?
If it helps at all, my enterValidCredentials class looks like this:
public class loginPageButtons {
private WebDriver driver;
Actions actions = new Actions(driver);
public class enterValidCredentials { // This class enters in a valid username and valid password on the login page.
public void enterValidCredentials2() {
driver.findElement(By.cssSelector("input[type=\"text\"]")).clear();
driver.findElement(By.cssSelector("input[type=\"text\"]")).sendKeys("XXXXXXXX");
driver.findElement(By.cssSelector("input[type=\"password\"]")).clear();
driver.findElement(By.cssSelector("input[type=\"password\"]")).sendKeys("XXXXXXXX");
}
}
All my other functions follow a relatively similar structure (depending on their function, of course).
You can use a unit test to check single functionalities of your classes.
The most used library to create unit tests is JUnit.
If you use an ide (like IntelliJ or Eclipse) running the test can be done with a simple command exactly as running a main method.
If you need to create mocks of your objects you can use a library like Mockito (but there are many other valid alternatives).
Note: A mock is an object that has the same interface as a complex object that is difficult to use in a test environment (for example a db connection, a file handler, a network handler).
Here is an example, I tried to imagine your code and a possible test. I assumed that clickLoginButton returns an integer just to show a possible assert statement.
Example:
#Test
public static void testCredentials() {
WebDriver driver = new FirefoxDriver();
driver.get("http://mail.google.com/");
EnterValidCredentials enterValidCredentials = new EnterValidCredentials(); // Or create a mock if necessary
// Set values if necessary
int returnValue = enterValidCredentials.clickLoginButton();
assertEquals(returnValue, 1);
}
I am writing camel unit test. One service that I interface with is Solr. After testing with mocks, I want to write tests that bring up a local solr instance.
So far I have tried to leverage the RestTestBase Solr class (org.apache.solr.util.RestTestBase). Because I am writing a unit test, I have not extended the class, merely tried to use the static methods it provides. The following does not work:
RestTestBase.createJettyAndHarness("src/test/resources/solr",
"solrconfig.xml", "schema.xml",
"/solr", true, null);
int solrPort = RestTestBase.jetty.getLocalPort();
String solrURL = "localhost:"+Integer.toString(solrPort)+"/solr";
...
I included solr and jetty in my pom. Any suggestions for how to programmatic stand up and shut down a solr instance? (because i am using camel unit testing, i prefer not to extend RestTestBase)
see the camel-solr unit tests for some complete examples....SolrComponentTestSupport
basically this...
#BeforeClass
public static void beforeClass() throws Exception {
// Set appropriate paths for Solr to use.
System.setProperty("solr.solr.home", "src/test/resources/solr");
System.setProperty("solr.data.dir", "target/test-classes/solr/data");
// Instruct Solr to keep the index in memory, for faster testing.
System.setProperty("solr.directoryFactory", "solr.RAMDirectoryFactory");
// Start a Solr instance.
solrRunner = new JettySolrRunner("src/test/resources/solr", "/solr", getPort());
solrRunner.start();
solrServer = new HttpSolrServer("http://localhost:" + getPort() + "/solr");
}
#AfterClass
public static void afterClass() throws Exception {
if (solrRunner != null) {
solrRunner.stop();
}
}