Way to test Metrics.Counter value as done with Aggregator - java

With Aggregators being removed as of Beam 2, is there a preferred way to test Counter value, like I did with Aggregators:
assertThat(tester.getAggregatorValue(fn.success)).isEqualTo(1);
assertThat(tester.getAggregatorValue(fn.failure)).isEqualTo(0);
assertThat(tester.getAggregatorValue(fn.empty)).isEqualTo(0);
Where tester is an instance od DoFnTester class and fn instance of my DoFn implementation, with aggregators success, failure and empty being final package-private visible fields.

This is similar to a question asked on the user#beam.apache.org list recently.
The answer there suggested installing a MetricsContainerImpl before running the test, and interacting with that, like Beam does for its existing tests (eg., LateDataDroppingDoFnRunnerTest).
They also encapsulated it in a TestRule:
#Rule TestMetrics metrics = new TestMetrics();
#Test
public void invalids() {
final DoFnTester<InputT, OutputT> doFnTester =
DoFnTester.of(fixture);
doFnTester.processElement(input);
assertThat(metrics,counterValue(fixture.ctr), is(1L));
}

Related

How to set Mock to have a default behavior and can override it in some test

I want to mock a dependency and return a default value in most test cases since most of them should not care about the values returned but there are some certain cases like I would like to test like the dependency returns some weird values or just throw. So I am modeling it in this way. Most cases, it should return a nice and valid value.
Test Setup which return the 20L by default for all test classes.
Dependency dependency = Mockito.mock(Dependency.class);
when(dependency.returnSomeVal()).thenReturn(20L);
In a specific test cases class, I would like to override the behavior like below:
when(dependency.returnSomeVal()).thenThrow(); //failure cases
when(dependency.returnSomeVal()).thenReturn(Weird_Val); //failure cases
But I don't find a good solution to override the existing behavior? Any idea?
You can reset the mock and add behavior. In the test, do
Mockito.reset(dependency);
when(dependency.returnSomeVal()).thenThrow(); //failure cases
when(dependency.returnSomeVal()).thenReturn(Weird_Val); //failure cases
Resetting will remove all mocked behavior on this class though. If you want to remock only some methods, then you have to create the mock from scratch.
I ended using myself this pattern to mock a bunch of methods of a class providing configurations.
In a #Before method I setup a bunch of stubs for a mocked object that provide a correct configuration for each test. Afterwards, in each test it was extremely convenient to only override one of those stubs to provide a different configuration and test a different error case.
I think the response from Hari Menon is correct but it somehow defeats the purpose explained in the question. If the mock is reset, all the stubs would need to be added again, making this pattern very confusing (it would be better to not use any overriding than using reset in this case, the code would be way more straightforward).
The comments added to the question provide indeed an indirect answer on how to achieve this, and why it works, but it took me a bit to get it working.
In spite of one of the comments, I made everything work by using in my #Before fixture when().thenReturn() and overriding the concrete stub with doReturn().when()
Example:
public class WorkerTest {
private ConfigProvider mockedConfigProvider = mock(ConfigProvider.class);
#Before
public void setup() {
// Setup stubs with a correct config
when(mockedConfigProvider.getValue("property1")).thenReturn("value1");
when(mockedConfigProvider.getValue("property2")).thenReturn("value2");
when(mockedConfigProvider.getValue("property3")).thenReturn("value3");
when(mockedConfigProvider.getValue("property4")).thenReturn("value4");
}
#Test
public void test_GoodConfig(){
// The config object gets injected in the test worker
Worker testWorker = new Worker(mockedConfigProvider);
// testWorker.execute() returns true if everything went well
assertTrue(testWorker.execute());
}
#Test
public void test_BadConfigProp1(){
// Test now with a broken 'property1', overriding that stub.
doReturn(null).when(mockedConfigProvider).getValue("property1");
Worker testWorker = new Worker(mockedConfigProvider);
// testWorker.execute() returns false if there is a problem.
assertFalse(testWorker.execute());
}
#Test
public void test_BadConfigProp2(){
// This test needs to only override the result of property2
doReturn("crazy result").when(mockedConfigProvider).getValue("property2");
...
}

How to use mockito to mock grpc ServiceBlockingStub to throw StatusRuntimeException(Status.UNAVAILABLE)?

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();
}

getting TestNG to treat class variables like JUnit with Guice

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).

Mocking a dependency on a property file

I'm trying to write a unit test that involves using legacy code. Problem is, from what I can tell, the legacy code uses a key/value pair from a property file to initialize one of its final static private members, and I haven't the slightest as to where that property file might be (the entire application is quite huge).
So, in my test, I want to do something like this (using Mockito):
LegacyClass legacyClass = mock(LegacyClass.class);
I end up getting a ExceptionInInitializationError which indicates it can't find a certain property key.
In LegacyClass.java, there's:
private static final int LEGACY_PROPERTY =
Integer.parseInt(LegacyPropertyManager.getProp("legacy.property.key"));
Is there a way to write a test that uses this legacy class, even if the property key it's looking for doesn't exist? Can it be mocked somehow?
You might not get very far without a clever library like PowerMock. Note that your LegacyClass.java initializes this property in a static final field, which means that the initializer will run as soon as it's loaded. PowerMock uses deeper magic (read: bytecode manipulation) to allow you to mock the static getProp method you cited above.
You'll need to do the following to get started with PowerMockito:
#RunWith(PowerMockRunner.class)
#PrepareForTest(LegacyPropertyManager.class)
public class YourClass {
#Before public void stubLegacyPropertyManager() {
Mockito.when(LegacyPropertyManager.getProp("legacy.property.key"))
.thenReturn("42");
}
#Test public void yourTest() {
// ...
}
}
Note the class-level annotations, which respectively allow for PowerMock initialization and register the correct class for static-level mocking.
An example of mocking a properties file, completely ignoring where it is would be the following. You can create your own set of key/value pairs right in the mocked properties object.
Properties mockProperties = mock(Properties.class);
when((mockProperties.getProperty("keyName"))).thenReturn("value");
Getting this object to be used by your legacy class may involve code changes to the legacy class such as changing the private properties object to protected or creating a set method.
When unable to enhance the legacy code, I know you can venture into the area of partial mocks/spies (Mockito 1.8) such as described in the following post .. Mockito bypass static method for testing and its link to Effective Mockito. I haven't used them so I cannot offer more help. Good luck.

gwt-log and gwt-test-utils not playing nice together

I've got a project that has gwt-log logging lines scattered throughout. Now I'm trying to write some unit tests and nothing seems to be working.
Any class I test that uses the gwt-log facility causes the following exception to be raised:
Caused by: com.googlecode.gwt.test.exceptions.GwtTestConfigurationException:
A custom Generator should be used to instanciate
'com.allen_sauer.gwt.log.client.LogMessageFormatter',
but gwt-test-utils does not support GWT compiler API,
so you have to add our own GwtCreateHandler with
'GwtTest.addGwtCreateHandler(..)' method or to declare your
tested object with #Mock
I have no need for the logger to function during unit tests, I'd prefer to mock it away.
I've attempted to use Mockito to mock the logger, in a few different ways... obviously I have no idea what I'm doing here, none of the following code snippets helped the situation:
public class ClockTest extends GwtTest {
#Mock private LogMessageFormatter lmf;
...
or
...
#Before
public void init() throws Exception {
LogMessageFormatter lmf = mock(LogMessageFormatter.class);
...
Any clues on how to work this out would be most appreciated!
Colin is right, you have 2 ways to deal with your error :
1) Mock the LogMessageFormatter, or at a higher level, mock your Logger instance. gwt-test-utils provides a simple API for mocking with both Mockito or EasyMock : http://code.google.com/p/gwt-test-utils/wiki/MockingClasses
2) provide your own GwtCreateHandler to instanciate the LogMessageFormatter, or at a higher your own Logger instance.
Internally, gwt-log relies on GWT's deferred binding to instanciate a LogMessageFormatter object based on your configuration, which is parsed at compile time. It use GWT's generator API to create the LogMessageFormatter class, but gwt-test-utils is not able to use those kind of Generators.
You'll have to do it "by hand", with gwt-test-utils deferred binding support : GwtCreateHandlers.
Your "LoggerGwtCreateHandler" could use JDK's InvocationHandler and Proxy classes to write a proxy for the Logger interface which would simply silent each method call, since I guess you won't care about any log call in your tests.
Here is a discussion on how to write a GwtCreateHandler : https://groups.google.com/forum/?fromgroups#!topic/gwt-test-utils-users/r_cbPsw9nIE
From the error message you posted:
you have to add our own GwtCreateHandler with
'GwtTest.addGwtCreateHandler(..)' method or to declare your
tested object with #Mock
These are the two options you have to proceed. I've only just begun to work with gwt-test-utils, but the main premise is that it doesn't run the GWT compiler or Dev Mode, so it needs other ways to handle implementing 'magic' features like GWT.create. Its method is to either require you to mock the instance (this should be a fairly common idea in most of your tests for other objects involved in testing) or to provide something like a generator, and hook it up using GwtTest.addGwtCreateHandler.
Building a mock logger shouldn't be too bad, nor should implementing GwtCreateHandler - you just need to make something that has all the log methods. If you want the logging to work, then those methods need to actually invoke some other logger, like java.util.Logger, log4j, slf4j, etc but that is not required for just getting the tests to run (but may be handy for making sure that you logging works, or finding out why your test is failing.
for those still in pain with this damn problem here is what I managed to get (With a lot of pain too ...). It'll solve the conflict between Gwt-test-utils and Gwt-log.
You're of course welcome to modify the format method ;) :
#Before
public void correctLog() {
this.addGwtCreateHandler(new GwtCreateHandler() {
#Override
public Object create(Class<?> classLiteral) throws Exception {
if (classLiteral.isAssignableFrom(LogMessageFormatter.class)) {
return new LogMessageFormatter() {
#Override
public String format(String logLevelText, String category,
String message, Throwable throwable) {
return message + " : " + throwable.getLocalizedMessage();
}
};
}
return null;
}
});
}

Categories