Skip to content

Improving Unit Test Coverage #100

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 76 commits into from
Dec 6, 2017
Merged

Improving Unit Test Coverage #100

merged 76 commits into from
Dec 6, 2017

Conversation

hiranya911
Copy link
Contributor

This PR adds more unit tests to cover classes like Connection, PersistentConnectionImpl and WebsocketConnection. To enable this, I also made some minor modifications to the classes in question, so they are more amenable to unit testing. Overall this brings our unit test coverage to 80%.

HostInfo hostInfo,
String cachedHost,
Delegate delegate,
String optLastSessionId,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I know it's not actually optional, but should this be the last argument?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored away

String optLastSessionId);
}

private static class DefaultConnectionFactory implements WebsocketConnectionFactory {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Can you come up with a more specific name for this? If WebsocketConnectionFactory wasn't already taken, I would suggest that as a name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to DefaultWebsocketConnectionFactory

@@ -262,6 +269,28 @@ public void injectConnectionFailure() {
REALTIME_DISCONNECTED
}

interface WebsocketConnectionFactory {
WebsocketConnection newConnection(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move some of this state to the factory instance? A lot of this shouldn't change after the initial creation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

realtime =
new Connection(this.context, this.hostInfo, this.cachedHost, this, this.lastSessionId);
realtime.open();
this.realtime = connFactory.newConnection(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be more in favor of removing 'this' from the other places rather than adding it everywhere.

Copy link
Contributor Author

@hiranya911 hiranya911 Dec 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this dereferences from the method body

long connId = connectionIds++;
this.hostInfo = hostInfo;
this.delegate = delegate;
this.logger = new LogWrapper(context.getLogger(), Connection.class, "conn_" + connId);
this.state = State.REALTIME_CONNECTING;
this.conn = new WebsocketConnection(context, hostInfo, cachedHost, this, optLastSessionId);
this.conn = connFactory.newConnection(context, hostInfo, cachedHost, this, optLastSessionId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we pass in the instance directly? It looks like at least this connection never gets recreated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to inject a reference to this into the created connection. Therefore, it must be done post construction.

FirebaseUserManager userManager = new FirebaseUserManager(gson, transport, credentials);
try {
userManager.getUserByEmail("[email protected]");
fail("No error thrown for invalid response");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the junit version you are using offer assertThrows()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are still on junit4. Lets upgrade to junit5 in a separate PR.

@@ -153,6 +185,74 @@ public void testDeleteUser() throws Exception {

@Test
public void testGetUserHttpError() throws Exception {
UserManagerOp[] operations = new UserManagerOp[]{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a map from Error Code to Callable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are multiple operations that return the same error code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to flip this map around? You could then use Map builders and remove about 50 lines in this file (No, I didn't count).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. (removed 33 lines :) )

.build());
Storage mockStorage = Mockito.mock(Storage.class);
StorageClient client = new StorageClient(app, mockStorage);
try {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and everywhere: Suggesting to use assertThrows.

Copy link
Contributor Author

@hiranya911 hiranya911 Dec 1, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertThrows is a junit5 method. We are still on junit4. Lets plan to do a upgrade in a future PR.

public void testTransactionError() throws InterruptedException {
final Repo repo = newRepo();
final List<DataSnapshot> events = new ArrayList<>();
final Path path = new Path("/txn_error");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm gonna use my knowledge that I just learned from Testing on the Toilet:

I think these tests would be easier to follow if you set up the mocks inline.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

assertTrue(executorService.isTerminated());
}

private static class CountingThreadFactory implements ThreadFactory {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hoping this was part of the JDK :/ This seems incredible useful!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to be supported by BasicThreadFactory of commons-lang. But we are currently not depending on it.

@hiranya911
Copy link
Contributor Author

I've made all the changes except for the use of generics for different factory types. I've left a follow up question regarding that.

@hiranya911 hiranya911 merged commit cc47045 into master Dec 6, 2017
@hiranya911 hiranya911 deleted the hkj-conn-test branch December 6, 2017 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants