ReRe is the abbreviation of Record and Replay. It is a Mockito code synthesizer, by recording real objects, and ReRe will produce code that mimics exactly that object's runtime behavior.
Hope you have fun with this project!
Check out our tutorials on Medium!
- Mocking the AWS DynamoDb client with ReRe
- Mocking a Jdbc SQL connection with ReRe
- Mocking the java HttpClient with ReRe
- Mocking a GRPC Client with ReRe
- Mocking the Apache HttpClient with ReRe
To start with ReRe, import the API first.
importorg.rere.api.ReRe;Next create a new instance of ReRe
ReRerere = newReRe();For whichever object you want to record, use the create root API. Here, we are using a dice as example.
// Create original objectDicedice = newDice();
// Create spied objectDicerereDice = rere.createSpiedObject(dice, Dice.class);Now rereDice is a copy of dice, that records its behavior. Use the rereDice inplace of dice in your code.
For example,
// Invoke method calls on the spied objectfor (inti = 0; i < 5; i++) {
rereDice.roll();
}After you are done recording, use the createMockito() api
// Export Mockito CodeStringcode = rere.exportMockito("org.rere.examples.readme", "create", "ReadmeExampleExpected");ReRe will generate the following code,
publicclassReadmeExampleExpected {
privatestaticfinalDefaultSerdedefaultSerde = newDefaultSerde();
publicstaticReadmeExample.DiceenvironmentNode0() {
ReadmeExample.DicemockObject = mock(ReadmeExample.Dice.class);
doReturn(4).doReturn(5).doReturn(2).doReturn(4).doReturn(3).when(mockObject).roll();
returnmockObject;
}
}Of course, ReRe is capable of more than just recording primitive value returns.
This following code is generated through ThrowExample.java, showing that ReRe can also capture throw behaviors.
publicclassThrowExampleExpected {
privatestaticfinalDefaultSerdedefaultSerde = newDefaultSerde();
publicstaticRuntimeExceptionenvironmentNode1() {
return (RuntimeException) defaultSerde.deserialize("rO0ABXNyABpqYXZhLmxhbmcuUnVudGltZUV4Y2VwdGlvbp5fBkcKNIPlAgAAeHIAE2phdmEubGFuZy5FeGNlcHRpb27Q/R8+GjscxAIAAHhyABNqYXZhLmxhbmcuVGhyb3dhYmxl1cY1Jzl3uMsDAARMAAVjYXVzZXQAFUxqYXZhL2xhbmcvVGhyb3dhYmxlO0wADWRldGFpbE1lc3NhZ2V0ABJMamF2YS9sYW5nL1N0cmluZztbAApzdGFja1RyYWNldAAeW0xqYXZhL2xhbmcvU3RhY2tUcmFjZUVsZW1lbnQ7TAAUc3VwcHJlc3NlZEV4Y2VwdGlvbnN0ABBMamF2YS91dGlsL0xpc3Q7eHBxAH4AB3QAHmRpY2UgdGhyb3dzIG9uIDNyZCBpbnZvY2F0aW9uLnVyAB5bTGphdmEubGFuZy5TdGFja1RyYWNlRWxlbWVudDsCRio8PP0iOQIAAHhwAAAAWXNyABtqYXZhLmxhbmcuU3RhY2tUcmFjZUVsZW1lbnRhCcWaJjbdhQIACEIABmZvcm1hdEkACmxpbmVOdW1iZXJMAA9jbGFzc0xvYWRlck5hbWVxAH4ABEwADmRlY2xhcmluZ0NsYXNzcQB+AARMAAhmaWxlTmFtZXEAfgAETAAKbWV0aG9kTmFtZXEAfgAETAAKbW9kdWxlTmFtZXEAfgAETAANbW9kdWxlVmVyc2lvbnEAfgAEeHABAAAAMXQAA2FwcHQAMm9yZy5yZXJlLmV4YW1wbGVzLmV4Y2VwdGlvbi5UaHJvd0V4YW1wbGUkRXJyb3JEaWNldAARVGhyb3dFeGFtcGxlLmphdmF0AARyb2xscHBzcQB+AAsCAAAAZ3B0AC9qZGsuaW50ZXJuYWwucmVmbGVjdC5EaXJlY3RNZXRob2RIYW5kbGVBY2Nlc3NvcnQAH0RpcmVjdE1ldGhvZEhhbmRsZUFjY2Vzc29yLmphdmF0AAZpbnZva2V0AAlqYXZhLmJhc2V0AAYyMS4wLjFzcQB+AAsCAAACRHB0ABhqYXZhLmxhbmcucmVmbGVjdC5NZXRob2R0AAtNZXRob2QuamF2YXEAfgAUcQB+ABVxAH4AFnNxAH4ACwEAAABTcQB+AA10ADxvcmcucmVyZS5jb3JlLmxpc3RlbmVyLmludGVyY2VwdG9yLkVudmlyb25tZW50T2JqZWN0TGlzdGVuZXJ0AB5FbnZpcm9ubWVudE9iamVjdExpc3RlbmVyLmphdmF0ABJpbnRlcmNlcHRJbnRlcmZhY2VwcHNxAH4ACwEAAAAccQB+AA1xAH4AG3EAfgAccQB+AB1wcHNxAH4ACwEAAAA9cQB+AA10AEVvcmcucmVyZS5jb3JlLmxpc3RlbmVyLndyYXAuYnl0ZWJ1ZGR5LkVudmlyb25tZW50Tm9kZVdyYXBwZXIkTGlzdGVuZXJ0ABtFbnZpcm9ubWVudE5vZGVXcmFwcGVyLmphdmF0AAlpbnRlcmNlcHRwcHNxAH4ACwD/////cHQARW9yZy5yZXJlLmV4YW1wbGVzLmV4Y2VwdGlvbi5UaHJvd0V4YW1wbGUkRXJyb3JEaWNlJEJ5dGVCdWRkeSQ0N0liaVN0Q3BxAH4AEHBwc3EAfgALAQAAABhxAH4ADXQAKG9yZy5yZXJlLmV4YW1wbGVzLmV4Y2VwdGlvbi5UaHJvd0V4YW1wbGVxAH4AD3QABG1haW5wcHNxAH4ACwEAAACdcQB+AA10AB5vcmcucmVyZS5leGFtcGxlcy5FeGFtcGxlVGVzdHN0ABFFeGFtcGxlVGVzdHMuamF2YXQAEHRlc3RUaHJvd0V4YW1wbGVwcHNxAH4ACwIAAABncHEAfgAScQB+ABNxAH4AFHEAfgAVcQB+ABZzcQB+AAsCAAACRHBxAH4AGHEAfgAZcQB+ABRxAH4AFXEAfgAWc3EAfgALAQAAAv1xAH4ADXQAL29yZy5qdW5pdC5wbGF0Zm9ybS5jb21tb25zLnV0aWwuUmVmbGVjdGlvblV0aWxzdAAUUmVmbGVjdGlvblV0aWxzLmphdmF0AAxpbnZva2VNZXRob2RwcHNxAH4ACwEAAAA8cQB+AA10ADNvcmcuanVuaXQuanVwaXRlci5lbmdpbmUuZXhlY3V0aW9uLk1ldGhvZEludm9jYXRpb250ABVNZXRob2RJbnZvY2F0aW9uLmphdmF0AAdwcm9jZWVkcHBzcQB+AAsBAAAAg3EAfgANdABSb3JnLmp1bml0Lmp1cGl0ZXIuZW5naW5lLmV4ZWN1dGlvbi5JbnZvY2F0aW9uSW50ZXJjZXB0b3JDaGFpbiRWYWxpZGF0aW5nSW52b2NhdGlvbnQAH0ludm9jYXRpb25JbnRlcmNlcHRvckNoYWluLmphdmFxAH4ANXBwc3EAfgALAQAAAJxxAH4ADXQAM29yZy5qdW5pdC5qdXBpdGVyLmVuZ2luZS5leHRlbnNpb24uVGltZW91dEV4dGVuc2lvbnQAFVRpbWVvdXRFeHRlbnNpb24uamF2YXEAfgAicHBzcQB+AAsBAAAAk3EAfgANcQB+ADpxAH4AO3QAF2ludGVyY2VwdFRlc3RhYmxlTWV0aG9kcHBzcQB+AAsBAAAAVnEAfgANcQB+ADpxAH4AO3QAE2ludGVyY2VwdFRlc3RNZXRob2RwcHNxAH4ACwEAAABncQB+AA10AFpvcmcuanVuaXQuanVwaXRlci5lbmdpbmUuZXhlY3V0aW9uLkludGVyY2VwdGluZ0V4ZWN1dGFibGVJbnZva2VyJFJlZmxlY3RpdmVJbnRlcmNlcHRvckNhbGx0ACJJbnRlcmNlcHRpbmdFeGVjdXRhYmxlSW52b2tlci5qYXZhdAAVbGFtYmRhJG9mVm9pZE1ldGhvZCQwcHBzcQB+AAsBAAAAXXEAfgANdABAb3JnLmp1bml0Lmp1cGl0ZXIuZW5naW5lLmV4ZWN1dGlvbi5JbnRlcmNlcHRpbmdFeGVjdXRhYmxlSW52b2tlcnEAfgBCdAAPbGFtYmRhJGludm9rZSQwcHBzcQB+AAsBAAAAanEAfgANdABTb3JnLmp1bml0Lmp1cGl0ZXIuZW5naW5lLmV4ZWN1dGlvbi5JbnZvY2F0aW9uSW50ZXJjZXB0b3JDaGFpbiRJbnRlcmNlcHRlZEludm9jYXRpb25xAH4AOHEAfgA1cHBzcQB+AAsBAAAAQHEAfgANdAA9b3JnLmp1bml0Lmp1cGl0ZXIuZW5naW5lLmV4ZWN1dGlvbi5JbnZvY2F0aW9uSW50ZXJjZXB0b3JDaGFpbnEAfgA4cQB+ADVwcHNxAH4ACwEAAAAtcQB+AA1xAH4ASnEAfgA4dAAOY2hhaW5BbmRJbnZva2VwcHNxAH4ACwEAAAAlcQB+AA1xAH4ASnEAfgA4cQB+ABRwcHNxAH4ACwEAAABccQB+AA1xAH4ARXEAfgBCcQB+ABRwcHNxAH4ACwEAAABWcQB+AA1xAH4ARXEAfgBCcQB+ABRwcHNxAH4ACwEAAADacQB+AA10ADxvcmcuanVuaXQuanVwaXRlci5lbmdpbmUuZGVzY3JpcHRvci5UZXN0TWV0aG9kVGVzdERlc2NyaXB0b3J0AB1UZXN0TWV0aG9kVGVzdERlc2NyaXB0b3IuamF2YXQAGWxhbWJkYSRpbnZva2VUZXN0TWV0aG9kJDdwcHNxAH4ACwEAAABJcQB+AA10AEFvcmcuanVuaXQucGxhdGZvcm0uZW5naW5lLnN1cHBvcnQuaGllcmFyY2hpY2FsLlRocm93YWJsZUNvbGxlY3RvcnQAF1Rocm93YWJsZUNvbGxlY3Rvci5qYXZhdAAHZXhlY3V0ZXBwc3EAfgALAQAAANZxAH4ADXEAfgBRcQB+AFJ0ABBpbnZva2VUZXN0TWV0aG9kcHBzcQB+AAsBAAAAi3EAfgANcQB+AFFxAH4AUnEAfgBXcHBzcQB+AAsBAAAARXEAfgANcQB+AFFxAH4AUnEAfgBXcHBzcQB+AAsBAAAAl3EAfgANdAA7b3JnLmp1bml0LnBsYXRmb3JtLmVuZ2luZS5zdXBwb3J0LmhpZXJhcmNoaWNhbC5Ob2RlVGVzdFRhc2t0ABFOb2RlVGVzdFRhc2suamF2YXQAG2xhbWJkYSRleGVjdXRlUmVjdXJzaXZlbHkkNnBwc3EAfgALAQAAAElxAH4ADXEAfgBVcQB+AFZxAH4AV3Bwc3EAfgALAQAAAI1xAH4ADXEAfgBdcQB+AF50ABtsYW1iZGEkZXhlY3V0ZVJlY3Vyc2l2ZWx5JDhwcHNxAH4ACwEAAACJcQB+AA10ADNvcmcuanVuaXQucGxhdGZvcm0uZW5naW5lLnN1cHBvcnQuaGllcmFyY2hpY2FsLk5vZGV0AAlOb2RlLmphdmF0AAZhcm91bmRwcHNxAH4ACwEAAACLcQB+AA1xAH4AXXEAfgBedAAbbGFtYmRhJGV4ZWN1dGVSZWN1cnNpdmVseSQ5cHBzcQB+AAsBAAAASXEAfgANcQB+AFVxAH4AVnEAfgBXcHBzcQB+AAsBAAAAinEAfgANcQB+AF1xAH4AXnQAEmV4ZWN1dGVSZWN1cnNpdmVseXBwc3EAfgALAQAAAF9xAH4ADXEAfgBdcQB+AF5xAH4AV3Bwc3EAfgALAgAABjxwdAATamF2YS51dGlsLkFycmF5TGlzdHQADkFycmF5TGlzdC5qYXZhdAAHZm9yRWFjaHEAfgAVcQB+ABZzcQB+AAsBAAAAKXEAfgANdABYb3JnLmp1bml0LnBsYXRmb3JtLmVuZ2luZS5zdXBwb3J0LmhpZXJhcmNoaWNhbC5TYW1lVGhyZWFkSGllcmFyY2hpY2FsVGVzdEV4ZWN1dG9yU2VydmljZXQALlNhbWVUaHJlYWRIaWVyYXJjaGljYWxUZXN0RXhlY3V0b3JTZXJ2aWNlLmphdmF0AAlpbnZva2VBbGxwcHNxAH4ACwEAAACbcQB+AA1xAH4AXXEAfgBecQB+AF9wcHNxAH4ACwEAAABJcQB+AA1xAH4AVXEAfgBWcQB+AFdwcHNxAH4ACwEAAACNcQB+AA1xAH4AXXEAfgBecQB+AGJwcHNxAH4ACwEAAACJcQB+AA1xAH4AZHEAfgBlcQB+AGZwcHNxAH4ACwEAAACLcQB+AA1xAH4AXXEAfgBecQB+AGhwcHNxAH4ACwEAAABJcQB+AA1xAH4AVXEAfgBWcQB+AFdwcHNxAH4ACwEAAACKcQB+AA1xAH4AXXEAfgBecQB+AGtwcHNxAH4ACwEAAABfcQB+AA1xAH4AXXEAfgBecQB+AFdwcHNxAH4ACwIAAAY8cHEAfgBucQB+AG9xAH4AcHEAfgAVcQB+ABZzcQB+AAsBAAAAKXEAfgANcQB+AHJxAH4Ac3EAfgB0cHBzcQB+AAsBAAAAm3EAfgANcQB+AF1xAH4AXnEAfgBfcHBzcQB+AAsBAAAASXEAfgANcQB+AFVxAH4AVnEAfgBXcHBzcQB+AAsBAAAAjXEAfgANcQB+AF1xAH4AXnEAfgBicHBzcQB+AAsBAAAAiXEAfgANcQB+AGRxAH4AZXEAfgBmcHBzcQB+AAsBAAAAi3EAfgANcQB+AF1xAH4AXnEAfgBocHBzcQB+AAsBAAAASXEAfgANcQB+AFVxAH4AVnEAfgBXcHBzcQB+AAsBAAAAinEAfgANcQB+AF1xAH4AXnEAfgBrcHBzcQB+AAsBAAAAX3EAfgANcQB+AF1xAH4AXnEAfgBXcHBzcQB+AAsBAAAAI3EAfgANcQB+AHJxAH4Ac3QABnN1Ym1pdHBwc3EAfgALAQAAADlxAH4ADXQAR29yZy5qdW5pdC5wbGF0Zm9ybS5lbmdpbmUuc3VwcG9ydC5oaWVyYXJjaGljYWwuSGllcmFyY2hpY2FsVGVzdEV4ZWN1dG9ydAAdSGllcmFyY2hpY2FsVGVzdEV4ZWN1dG9yLmphdmFxAH4AV3Bwc3EAfgALAQAAADZxAH4ADXQARW9yZy5qdW5pdC5wbGF0Zm9ybS5lbmdpbmUuc3VwcG9ydC5oaWVyYXJjaGljYWwuSGllcmFyY2hpY2FsVGVzdEVuZ2luZXQAG0hpZXJhcmNoaWNhbFRlc3RFbmdpbmUuamF2YXEAfgBXcHBzcQB+AAsBAAAAa3EAfgANdAA8b3JnLmp1bml0LnBsYXRmb3JtLmxhdW5jaGVyLmNvcmUuRW5naW5lRXhlY3V0aW9uT3JjaGVzdHJhdG9ydAAgRW5naW5lRXhlY3V0aW9uT3JjaGVzdHJhdG9yLmphdmFxAH4AV3Bwc3EAfgALAQAAAFhxAH4ADXEAfgCQcQB+AJFxAH4AV3Bwc3EAfgALAQAAADZxAH4ADXEAfgCQcQB+AJF0ABBsYW1iZGEkZXhlY3V0ZSQwcHBzcQB+AAsBAAAAQ3EAfgANcQB+AJBxAH4AkXQAFndpdGhJbnRlcmNlcHRlZFN0cmVhbXNwcHNxAH4ACwEAAAA0cQB+AA1xAH4AkHEAfgCRcQB+AFdwcHNxAH4ACwEAAABycQB+AA10ADBvcmcuanVuaXQucGxhdGZvcm0ubGF1bmNoZXIuY29yZS5EZWZhdWx0TGF1bmNoZXJ0ABREZWZhdWx0TGF1bmNoZXIuamF2YXEAfgBXcHBzcQB+AAsBAAAAVnEAfgANcQB+AJlxAH4AmnEAfgBXcHBzcQB+AAsBAAAAVnEAfgANdABKb3JnLmp1bml0LnBsYXRmb3JtLmxhdW5jaGVyLmNvcmUuRGVmYXVsdExhdW5jaGVyU2Vzc2lvbiREZWxlZ2F0aW5nTGF1bmNoZXJ0ABtEZWZhdWx0TGF1bmNoZXJTZXNzaW9uLmphdmFxAH4AV3Bwc3EAfgALAAAAAHdwdABxb3JnLmdyYWRsZS5hcGkuaW50ZXJuYWwudGFza3MudGVzdGluZy5qdW5pdHBsYXRmb3JtLkpVbml0UGxhdGZvcm1UZXN0Q2xhc3NQcm9jZXNzb3IkQ29sbGVjdEFsbFRlc3RDbGFzc2VzRXhlY3V0b3J0ACRKVW5pdFBsYXRmb3JtVGVzdENsYXNzUHJvY2Vzc29yLmphdmF0ABVwcm9jZXNzQWxsVGVzdENsYXNzZXNwcHNxAH4ACwAAAABecHEAfgCgcQB+AKF0AAphY2Nlc3MkMDAwcHBzcQB+AAsAAAAAWXB0AFNvcmcuZ3JhZGxlLmFwaS5pbnRlcm5hbC50YXNrcy50ZXN0aW5nLmp1bml0cGxhdGZvcm0uSlVuaXRQbGF0Zm9ybVRlc3RDbGFzc1Byb2Nlc3NvcnEAfgChdAAEc3RvcHBwc3EAfgALAAAAAD5wdAA9b3JnLmdyYWRsZS5hcGkuaW50ZXJuYWwudGFza3MudGVzdGluZy5TdWl0ZVRlc3RDbGFzc1Byb2Nlc3NvcnQAHFN1aXRlVGVzdENsYXNzUHJvY2Vzc29yLmphdmFxAH4Ap3Bwc3EAfgALAgAAAGdwcQB+ABJxAH4AE3EAfgAUcQB+ABVxAH4AFnNxAH4ACwIAAAJEcHEAfgAYcQB+ABlxAH4AFHEAfgAVcQB+ABZzcQB+AAsAAAAAJHB0AC9vcmcuZ3JhZGxlLmludGVybmFsLmRpc3BhdGNoLlJlZmxlY3Rpb25EaXNwYXRjaHQAF1JlZmxlY3Rpb25EaXNwYXRjaC5qYXZhdAAIZGlzcGF0Y2hwcHNxAH4ACwAAAAAYcHEAfgCucQB+AK9xAH4AsHBwc3EAfgALAAAAACFwdAA3b3JnLmdyYWRsZS5pbnRlcm5hbC5kaXNwYXRjaC5Db250ZXh0Q2xhc3NMb2FkZXJEaXNwYXRjaHQAH0NvbnRleHRDbGFzc0xvYWRlckRpc3BhdGNoLmphdmFxAH4AsHBwc3EAfgALAAAAAF5wdABOb3JnLmdyYWRsZS5pbnRlcm5hbC5kaXNwYXRjaC5Qcm94eURpc3BhdGNoQWRhcHRlciREaXNwYXRjaGluZ0ludm9jYXRpb25IYW5kbGVydAAZUHJveHlEaXNwYXRjaEFkYXB0ZXIuamF2YXEAfgAUcHBzcQB+AAsA/////3B0ABJqZGsucHJveHkyLiRQcm94eTVwcQB+AKd0AApqZGsucHJveHkycHNxAH4ACwAAAADBcHQAOW9yZy5ncmFkbGUuYXBpLmludGVybmFsLnRhc2tzLnRlc3Rpbmcud29ya2VyLlRlc3RXb3JrZXIkM3QAD1Rlc3RXb3JrZXIuamF2YXQAA3J1bnBwc3EAfgALAAAAAIFwdAA3b3JnLmdyYWRsZS5hcGkuaW50ZXJuYWwudGFza3MudGVzdGluZy53b3JrZXIuVGVzdFdvcmtlcnEAfgC9dAAcZXhlY3V0ZUFuZE1haW50YWluVGhyZWFkTmFtZXBwc3EAfgALAAAAAGRwcQB+AMBxAH4AvXEAfgBXcHBzcQB+AAsAAAAAPHBxAH4AwHEAfgC9cQB+AFdwcHNxAH4ACwAAAAA4cHQAPm9yZy5ncmFkbGUucHJvY2Vzcy5pbnRlcm5hbC53b3JrZXIuY2hpbGQuQWN0aW9uRXhlY3V0aW9uV29ya2VydAAaQWN0aW9uRXhlY3V0aW9uV29ya2VyLmphdmFxAH4AV3Bwc3EAfgALAAAAAHFwdABLb3JnLmdyYWRsZS5wcm9jZXNzLmludGVybmFsLndvcmtlci5jaGlsZC5TeXN0ZW1BcHBsaWNhdGlvbkNsYXNzTG9hZGVyV29ya2VydAAnU3lzdGVtQXBwbGljYXRpb25DbGFzc0xvYWRlcldvcmtlci5qYXZhdAAEY2FsbHBwc3EAfgALAAAAAEFwcQB+AMhxAH4AyXEAfgDKcHBzcQB+AAsBAAAARXEAfgANdAA6d29ya2VyLm9yZy5ncmFkbGUucHJvY2Vzcy5pbnRlcm5hbC53b3JrZXIuR3JhZGxlV29ya2VyTWFpbnQAFUdyYWRsZVdvcmtlck1haW4uamF2YXEAfgC+cHBzcQB+AAsBAAAASnEAfgANcQB+AM1xAH4AznEAfgAncHBzcgAfamF2YS51dGlsLkNvbGxlY3Rpb25zJEVtcHR5TGlzdHq4F7Q8p57eAgAAeHB4");
}
publicstaticThrowExample.ErrorDiceenvironmentNode0() {
ThrowExample.ErrorDicemockObject = mock(ThrowExample.ErrorDice.class);
doReturn(2).doReturn(2).doThrow(environmentNode1()).doReturn(1).doReturn(4).when(mockObject).roll();
returnmockObject;
}
}This following code is generated through SortExample.java, showing that ReRe also captures modifications to the parameters.
publicclassSortExampleExpected {
privatestaticfinalDefaultSerdedefaultSerde = newDefaultSerde();
publicstaticAnswer<Void> getAnswer0() {
return (InvocationOnMockinvocation) -> {
ArrayListparam0 = invocation.getArgument(0);
param0.size();
SortExample.MyIntreturn1 = (SortExample.MyInt) param0.get(1);
SortExample.MyIntreturn2 = (SortExample.MyInt) param0.get(0);
return1.compare(return2);
param0.set(1, return2);
param0.set(0, return1);
SortExample.MyIntreturn6 = (SortExample.MyInt) param0.get(1);
SortExample.MyIntreturn7 = (SortExample.MyInt) param0.get(0);
return6.compare(return7);
returnnull;
} ;
}
publicstaticSortExample.BubbleSorterenvironmentNode0() {
SortExample.BubbleSortermockObject = mock(SortExample.BubbleSorter.class);
doAnswer(getAnswer0()).when(mockObject).sort(any());
returnmockObject;
}
}This last example is from IdentityFunctionExample.java, show casing ReRe can also record the behavior of identity functions. This is important, since returning an object copy instead of an object with the same reference may cause replay failures.
publicclassIdentityFunctionExampleExpected {
privatestaticfinalDefaultSerdedefaultSerde = newDefaultSerde();
publicstaticAnswer<ArrayList> getAnswer0() {
return (InvocationOnMockinvocation) -> {
ArrayListparam0 = invocation.getArgument(0);
returnparam0;
} ;
}
publicstaticIdentityFunctionExample.IdentityFunctionenvironmentNode0() {
IdentityFunctionExample.IdentityFunctionmockObject = mock(IdentityFunctionExample.IdentityFunction.class);
doAnswer(getAnswer0()).when(mockObject).call(any());
returnmockObject;
}
}All our examples are also run as unit tests, please check test/java/org/rere/examples for more usage examples.
We cannot record the behavior of final objects, since the lower level implementation of interception is done by subclassing. We will in the future, provide custom serialization as a workaround.
Modifications to global variables as a side effect are not recorded. In the future, we may provide a solution for users to manually mark the possible global variables that are modified, and record the side effects.
ReRe matches methods by the call order, since matching variables is probably an undecidable problem. The inconsistency of multithreaded programs may be a problem.
hashCode() and isEqual() might break, because we are subclassing.
Please raise issues for bugs, ask questions for usage. Let's talk about the problem before starting to implement code.
I'll set up a buy me a coffee link later. [link pending]
Right now any job referrals would help. Here is my resume [link pending]
There are also some projects that need funding:
- Python version of ReRe
- JavaScript version of ReRe
- Unnamed project - reconstruct code execution paths from log4j logs. (This is not an undecidable problem, given the line numbers.)
Thanks to all my friends and family. Many of whom I kept pitching this idea to.
Thanks to my former colleagues at Amazon. I received a lot of mentorship as a junior engineer there. A lot of the coding principles I learnt at Amazon inspired this project.
Special thanks to Joe Leija, who I pitched this idea multiple time towards, and getting feedback everytime.
Thanks to Rafael Winterhalter, the creator of ByteBuddy. This person may not know me, but I feel I know this person a lot. It is crazy how much he supports the ByteBuddy project online. This year I have read so much tutorials and answer written by himself. I doubt I will have the same energy to do for project ReRe.
Thanks to the authors of Mockito/EasyMock, and all the previous mock frameworks. I am standing on the shoulder of giants.