Prechádzať zdrojové kódy

Add JNI method call functionality to JniClass (incomplete)

This method call only support "getter" type method calls with
return type of byte.
Patrick-Christopher Mattulat 1 rok pred
rodič
commit
bb9460e2f5

+ 5 - 1
CMakeLists.txt

@@ -198,7 +198,9 @@ set(SOURCE_FILES_CORE_JNI
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/interface/IJniApi.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/jni/JniApi.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/jni/JniClass.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/jni/JniClassParameter.cpp)
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/jni/JniClassParameter.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/jni/JniMethod.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/core/jni/JniReturnValue.cpp)
 
 set(SOURCE_FILES_ENCODING
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls-std/encoding/Base64.cpp)
@@ -328,6 +330,8 @@ if (${LS_STD_BUILD_WITH_TESTS})
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/jni/JniApiTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/jni/JniClassParameterTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/jni/JniClassTest.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/jni/JniMethodTest.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/core/jni/JniReturnValueTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/core/jni/MockJniApi.cpp)
 
     set(UNIT_TEST_FILES_ENCODING

+ 2 - 1
include/ls-std/core/interface/IJniApi.hpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-04-07
-* Changed:         2023-04-07
+* Changed:         2023-04-08
 *
 * */
 
@@ -23,6 +23,7 @@ namespace ls::std::core::interface_type
       IJniApi();
       virtual ~IJniApi();
 
+      virtual jbyte callByteMethod(jobject _javaObject, jmethodID _methodId) = 0;
       virtual jclass findClass(const ::std::string &_classPath) = 0;
       virtual jmethodID getMethodId(jclass _javaClass, const char *_methodIdentifier, const char *_methodSignature) = 0;
   };

+ 2 - 1
include/ls-std/core/jni/JniApi.hpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-04-07
-* Changed:         2023-04-07
+* Changed:         2023-04-08
 *
 * */
 
@@ -22,6 +22,7 @@ namespace ls::std::core
       explicit JniApi(JNIEnv *_environment);
       ~JniApi() noexcept override;
 
+      jbyte callByteMethod(jobject _javaObject, jmethodID _methodId) override;
       jclass findClass(const ::std::string &_classPath) override;
       jmethodID getMethodId(jclass _javaClass, const char *_methodIdentifier, const char *_methodSignature) override;
 

+ 6 - 2
include/ls-std/core/jni/JniClass.hpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-04-07
-* Changed:         2023-04-07
+* Changed:         2023-04-08
 *
 * */
 
@@ -11,6 +11,8 @@
 #define LS_STD_JNI_CLASS_HPP
 
 #include "JniClassParameter.hpp"
+#include "JniMethod.hpp"
+#include "JniReturnValue.hpp"
 #include <jni.h>
 #include <ls-std/core/interface/IJniApi.hpp>
 #include <ls-std/os/dynamic-goal.hpp>
@@ -27,6 +29,7 @@ namespace ls::std::core
       explicit JniClass(const ::std::shared_ptr<ls::std::core::JniClassParameter> &_parameter, const ::std::string &_path);
       virtual ~JniClass();
 
+      [[nodiscard]] ls::std::core::JniReturnValue callMethod(const ::std::string &_methodIdentifier);
       [[nodiscard]] bool hasMethod(const ::std::string &_methodIdentifier);
       bool load();                                                                                    // nodiscard is optional here
       bool loadMethod(const ::std::string &_methodIdentifier, const ::std::string &_methodSignature); // nodiscard is optional here
@@ -34,10 +37,11 @@ namespace ls::std::core
     private:
 
       jclass javaClass{};
-      ::std::unordered_map<::std::string, jmethodID> methods{};
+      ::std::unordered_map<::std::string, ls::std::core::JniMethod> methods{};
       ::std::shared_ptr<ls::std::core::JniClassParameter> parameter{};
       ::std::string path{};
 
+      void _callByteMethod(const ::std::string &_methodIdentifier, ls::std::core::JniReturnValue &_returnValue);
       void _createJniApi();
       [[nodiscard]] bool _hasMethod(const ::std::string &_methodIdentifier);
   };

+ 4 - 1
include/ls-std/core/jni/JniClassParameter.hpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-04-07
-* Changed:         2023-04-07
+* Changed:         2023-04-08
 *
 * */
 
@@ -26,13 +26,16 @@ namespace ls::std::core
       ~JniClassParameter();
 
       [[nodiscard]] JNIEnv *getJavaEnvironment();
+      [[nodiscard]] jobject getJavaObject();
       [[nodiscard]] ::std::shared_ptr<ls::std::core::interface_type::IJniApi> getJniApi();
       void setJavaEnvironment(JNIEnv *_environment);
+      void setJavaObject(jobject _javaObject);
       void setJniApi(const ::std::shared_ptr<ls::std::core::interface_type::IJniApi> &_jniApi);
 
     private:
 
       JNIEnv *environment{};
+      jobject javaObject{};
       ::std::shared_ptr<ls::std::core::interface_type::IJniApi> jniApi{};
   };
 }

+ 41 - 0
include/ls-std/core/jni/JniMethod.hpp

@@ -0,0 +1,41 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-08
+* Changed:         2023-04-08
+*
+* */
+
+#ifndef LS_STD_JNI_METHOD_HPP
+#define LS_STD_JNI_METHOD_HPP
+
+#include <jni.h>
+#include <ls-std/os/dynamic-goal.hpp>
+#include <string>
+
+namespace ls::std::core
+{
+  class LS_STD_DYNAMIC_GOAL JniMethod
+  {
+    public:
+
+      explicit JniMethod(const ::std::string &_methodIdentifier, const ::std::string &_methodSignature);
+      ~JniMethod();
+
+      [[nodiscard]] jmethodID getMethodId();
+      [[nodiscard]] ::std::string getMethodIdentifier();
+      [[nodiscard]] ::std::string getMethodSignature();
+      void setMethodId(jmethodID _methodId);
+      void setMethodIdentifier(const ::std::string &_methodIdentifier);
+      void setMethodSignature(const ::std::string &_methodSignature);
+
+    private:
+
+      jmethodID methodId{};
+      ::std::string methodIdentifier{};
+      ::std::string methodSignature{};
+  };
+}
+
+#endif

+ 34 - 0
include/ls-std/core/jni/JniReturnValue.hpp

@@ -0,0 +1,34 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-08
+* Changed:         2023-04-08
+*
+* */
+
+#ifndef LS_STD_JNI_RETURN_VALUE_HPP
+#define LS_STD_JNI_RETURN_VALUE_HPP
+
+#include <jni.h>
+#include <ls-std/os/dynamic-goal.hpp>
+
+namespace ls::std::core
+{
+  class LS_STD_DYNAMIC_GOAL JniReturnValue
+  {
+    public:
+
+      JniReturnValue();
+      ~JniReturnValue();
+
+      [[nodiscard]] jbyte getByteValue() const;
+      void setByteValue(jbyte _byteValue);
+
+    private:
+
+      jbyte byteValue{};
+  };
+}
+
+#endif

+ 3 - 1
include/ls-std/ls-std-core-jni.hpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-04-07
-* Changed:         2023-04-07
+* Changed:         2023-04-08
 *
 * */
 
@@ -13,5 +13,7 @@
 #include <ls-std/core/jni/JniApi.hpp>
 #include <ls-std/core/jni/JniClass.hpp>
 #include <ls-std/core/jni/JniClassParameter.hpp>
+#include <ls-std/core/jni/JniMethod.hpp>
+#include <ls-std/core/jni/JniReturnValue.hpp>
 
 #endif

+ 6 - 1
source/ls-std/core/jni/JniApi.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-04-07
-* Changed:         2023-04-07
+* Changed:         2023-04-08
 *
 * */
 
@@ -22,6 +22,11 @@ JniApi::JniApi(JNIEnv *_environment)
 
 JniApi::~JniApi() noexcept = default;
 
+jbyte JniApi::callByteMethod(jobject _javaObject, jmethodID _methodId)
+{
+  return this->environment->CallByteMethod(_javaObject, _methodId);
+}
+
 jclass JniApi::findClass(const string &_classPath)
 {
   return this->environment->FindClass(_classPath.c_str());

+ 31 - 2
source/ls-std/core/jni/JniClass.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-04-07
-* Changed:         2023-04-07
+* Changed:         2023-04-08
 *
 * */
 
@@ -20,6 +20,8 @@ using ls::std::core::EmptyStringArgumentEvaluator;
 using ls::std::core::JniApi;
 using ls::std::core::JniClass;
 using ls::std::core::JniClassParameter;
+using ls::std::core::JniMethod;
+using ls::std::core::JniReturnValue;
 using ls::std::core::NullPointerArgumentEvaluator;
 using ls::std::core::NullPointerEvaluator;
 using std::make_pair;
@@ -40,6 +42,18 @@ JniClass::JniClass(const shared_ptr<JniClassParameter> &_parameter, const string
 
 JniClass::~JniClass() = default;
 
+JniReturnValue JniClass::callMethod(const string &_methodIdentifier)
+{
+  JniReturnValue returnValue{};
+
+  if (this->_hasMethod(_methodIdentifier))
+  {
+    this->_callByteMethod(_methodIdentifier, returnValue);
+  }
+
+  return returnValue;
+}
+
 bool JniClass::hasMethod(const string &_methodIdentifier)
 {
   return this->_hasMethod(_methodIdentifier);
@@ -59,12 +73,27 @@ bool JniClass::loadMethod(const string &_methodIdentifier, const string &_method
 
   if (succeeded)
   {
-    succeeded = this->methods.insert(make_pair<string, jmethodID>(string{_methodIdentifier}, jmethodID{methodId})).second;
+    JniMethod method{_methodIdentifier, _methodSignature};
+    method.setMethodId(methodId);
+    succeeded = this->methods.insert(make_pair<string, JniMethod>(string{_methodIdentifier}, JniMethod{method})).second;
   }
 
   return succeeded;
 }
 
+void JniClass::_callByteMethod(const string &_methodIdentifier, JniReturnValue &_returnValue)
+{
+  JniMethod method = this->methods.at(_methodIdentifier);
+  string searchString = ")B";
+  string methodSignature = method.getMethodSignature();
+  bool hasBooleanReturnType = methodSignature.rfind(searchString) == (methodSignature.size() - searchString.size());
+
+  if (hasBooleanReturnType)
+  {
+    _returnValue.setByteValue(this->parameter->getJniApi()->callByteMethod(this->parameter->getJavaObject(), method.getMethodId()));
+  }
+}
+
 void JniClass::_createJniApi()
 {
   this->parameter->setJniApi(make_shared<JniApi>(this->parameter->getJavaEnvironment()));

+ 11 - 1
source/ls-std/core/jni/JniClassParameter.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-04-07
-* Changed:         2023-04-07
+* Changed:         2023-04-08
 *
 * */
 
@@ -23,6 +23,11 @@ JNIEnv *JniClassParameter::getJavaEnvironment()
   return this->environment;
 }
 
+jobject JniClassParameter::getJavaObject()
+{
+  return this->javaObject;
+}
+
 shared_ptr<IJniApi> JniClassParameter::getJniApi()
 {
   return this->jniApi;
@@ -33,6 +38,11 @@ void JniClassParameter::setJavaEnvironment(JNIEnv *_environment)
   this->environment = _environment;
 }
 
+void JniClassParameter::setJavaObject(jobject _javaObject)
+{
+  this->javaObject = _javaObject;
+}
+
 void JniClassParameter::setJniApi(const shared_ptr<IJniApi> &_jniApi)
 {
   this->jniApi = _jniApi;

+ 55 - 0
source/ls-std/core/jni/JniMethod.cpp

@@ -0,0 +1,55 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-08
+* Changed:         2023-04-08
+*
+* */
+
+#include <ls-std/core/evaluator/EmptyStringArgumentEvaluator.hpp>
+#include <ls-std/core/jni/JniMethod.hpp>
+
+using ls::std::core::EmptyStringArgumentEvaluator;
+using ls::std::core::JniMethod;
+using std::string;
+
+JniMethod::JniMethod(const string &_methodIdentifier, const string &_methodSignature)
+{
+  EmptyStringArgumentEvaluator{_methodIdentifier}.evaluate();
+  EmptyStringArgumentEvaluator{_methodSignature}.evaluate();
+  this->methodIdentifier = _methodIdentifier;
+  this->methodSignature = _methodSignature;
+}
+
+JniMethod::~JniMethod() = default;
+
+jmethodID JniMethod::getMethodId()
+{
+  return this->methodId;
+}
+
+string JniMethod::getMethodIdentifier()
+{
+  return this->methodIdentifier;
+}
+
+string JniMethod::getMethodSignature()
+{
+  return this->methodSignature;
+}
+
+void JniMethod::setMethodId(jmethodID _methodId)
+{
+  this->methodId = _methodId;
+}
+
+void JniMethod::setMethodIdentifier(const string &_methodIdentifier)
+{
+  this->methodIdentifier = _methodIdentifier;
+}
+
+void JniMethod::setMethodSignature(const string &_methodSignature)
+{
+  this->methodSignature = _methodSignature;
+}

+ 26 - 0
source/ls-std/core/jni/JniReturnValue.cpp

@@ -0,0 +1,26 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-08
+* Changed:         2023-04-08
+*
+* */
+
+#include <ls-std/core/jni/JniReturnValue.hpp>
+
+using ls::std::core::JniReturnValue;
+
+JniReturnValue::JniReturnValue() = default;
+
+JniReturnValue::~JniReturnValue() = default;
+
+jbyte JniReturnValue::getByteValue() const
+{
+  return this->byteValue;
+}
+
+void JniReturnValue::setByteValue(jbyte _byteValue)
+{
+  this->byteValue = _byteValue;
+}

+ 23 - 8
test/cases/core/jni/JniClassParameterTest.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-04-07
-* Changed:         2023-04-07
+* Changed:         2023-04-08
 *
 * */
 
@@ -36,19 +36,16 @@ namespace
     ASSERT_TRUE(parameter.getJavaEnvironment() == nullptr);
   }
 
-  TEST_F(JniClassParameterTest, getJniApi)
+  TEST_F(JniClassParameterTest, getJavaObject)
   {
     JniClassParameter parameter{};
-    ASSERT_TRUE(parameter.getJniApi() == nullptr);
+    ASSERT_TRUE(parameter.getJavaObject() == nullptr);
   }
 
-  TEST_F(JniClassParameterTest, setJniApi)
+  TEST_F(JniClassParameterTest, getJniApi)
   {
     JniClassParameter parameter{};
-    shared_ptr<IJniApi> jniApi = make_shared<MockJniApi>();
-    parameter.setJniApi(jniApi);
-
-    ASSERT_TRUE(parameter.getJniApi() == jniApi);
+    ASSERT_TRUE(parameter.getJniApi() == nullptr);
   }
 
   TEST_F(JniClassParameterTest, setJavaEnvironment)
@@ -59,4 +56,22 @@ namespace
 
     ASSERT_TRUE(parameter.getJavaEnvironment() == environment.get());
   }
+
+  TEST_F(JniClassParameterTest, setJavaObject)
+  {
+    JniClassParameter parameter{};
+    shared_ptr<_jobject> javaObject = make_shared<_jobject>();
+    parameter.setJavaObject(javaObject.get());
+
+    ASSERT_TRUE(parameter.getJavaObject() == javaObject.get());
+  }
+
+  TEST_F(JniClassParameterTest, setJniApi)
+  {
+    JniClassParameter parameter{};
+    shared_ptr<IJniApi> jniApi = make_shared<MockJniApi>();
+    parameter.setJniApi(jniApi);
+
+    ASSERT_TRUE(parameter.getJniApi() == jniApi);
+  }
 }

+ 21 - 1
test/cases/core/jni/JniClassTest.cpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-04-07
-* Changed:         2023-04-07
+* Changed:         2023-04-08
 *
 * */
 
@@ -97,6 +97,26 @@ namespace
         IllegalArgumentException);
   }
 
+  TEST_F(JniClassTest, callMethod_byte_return_value)
+  {
+    string classPath = "java.utils.String";
+    JniClass javaClass = this->createJniClass(classPath);
+
+    EXPECT_CALL(*this->jniApi, findClass(classPath)).Times(AtLeast(1));
+    ON_CALL(*this->jniApi, findClass(classPath)).WillByDefault(Return(make_shared<_jclass>().get()));
+    string methodIdentifier = "getDay";
+    string methodSignature = "()B";
+    EXPECT_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).Times(AtLeast(1));
+    jmethodID methodId = (jmethodID) make_shared<int>().get();
+    ON_CALL(*this->jniApi, getMethodId(testing::_, methodIdentifier.c_str(), methodSignature.c_str())).WillByDefault(Return(methodId));
+    EXPECT_CALL(*this->jniApi, callByteMethod(testing::_, methodId)).Times(AtLeast(1));
+    ON_CALL(*this->jniApi, callByteMethod(testing::_, methodId)).WillByDefault(Return(22));
+
+    ASSERT_TRUE(javaClass.load());
+    ASSERT_TRUE(javaClass.loadMethod(methodIdentifier, methodSignature));
+    ASSERT_EQ(22, javaClass.callMethod(methodIdentifier).getByteValue());
+  }
+
   TEST_F(JniClassTest, hasMethod)
   {
     string classPath = "java.utils.String";

+ 104 - 0
test/cases/core/jni/JniMethodTest.cpp

@@ -0,0 +1,104 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-08
+* Changed:         2023-04-08
+*
+* */
+
+#include <gtest/gtest.h>
+#include <ls-std/ls-std-core-jni.hpp>
+#include <ls-std/ls-std-core.hpp>
+#include <memory>
+
+using ls::std::core::IllegalArgumentException;
+using ls::std::core::JniMethod;
+using std::make_shared;
+using testing::Test;
+
+namespace
+{
+  class JniMethodTest : public Test
+  {
+    public:
+
+      JniMethodTest() = default;
+      ~JniMethodTest() override = default;
+  };
+
+  TEST_F(JniMethodTest, constructor_empty_method_identifier)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            JniMethod method("", "()B");
+          }
+          catch (const IllegalArgumentException &_exception)
+          {
+            throw;
+          }
+        },
+        IllegalArgumentException);
+  }
+
+  TEST_F(JniMethodTest, constructor_empty_method_signature)
+  {
+    EXPECT_THROW(
+        {
+          try
+          {
+            JniMethod method("getDay", "");
+          }
+          catch (const IllegalArgumentException &_exception)
+          {
+            throw;
+          }
+        },
+        IllegalArgumentException);
+  }
+
+  TEST_F(JniMethodTest, getMethodId)
+  {
+    JniMethod method{"getDay", "()B"};
+    ASSERT_TRUE(method.getMethodId() == nullptr);
+  }
+
+  TEST_F(JniMethodTest, getMethodIdentifier)
+  {
+    JniMethod method{"getDay", "()B"};
+    ASSERT_STREQ("getDay", method.getMethodIdentifier().c_str());
+  }
+
+  TEST_F(JniMethodTest, getMethodSignature)
+  {
+    JniMethod method{"getDay", "()B"};
+    ASSERT_STREQ("()B", method.getMethodSignature().c_str());
+  }
+
+  TEST_F(JniMethodTest, setMethodId)
+  {
+    JniMethod method{"getDay", "()B"};
+    jmethodID methodId = (jmethodID) make_shared<int>().get();
+    method.setMethodId(methodId);
+
+    ASSERT_TRUE(method.getMethodId() == methodId);
+  }
+
+  TEST_F(JniMethodTest, setMethodIdentifier)
+  {
+    JniMethod method{"getDay", "()B"};
+    method.setMethodIdentifier("getHour");
+
+    ASSERT_STREQ("getHour", method.getMethodIdentifier().c_str());
+  }
+
+  TEST_F(JniMethodTest, setMethodSignature)
+  {
+    JniMethod method{"getDay", "()B"};
+    method.setMethodSignature("()I");
+
+    ASSERT_STREQ("()I", method.getMethodSignature().c_str());
+  }
+}

+ 39 - 0
test/cases/core/jni/JniReturnValueTest.cpp

@@ -0,0 +1,39 @@
+/*
+* Author:          Patrick-Christopher Mattulat
+* Company:         Lynar Studios
+* E-Mail:          webmaster@lynarstudios.com
+* Created:         2023-04-08
+* Changed:         2023-04-08
+*
+* */
+
+#include <gtest/gtest.h>
+#include <ls-std/ls-std-core-jni.hpp>
+
+using ls::std::core::JniReturnValue;
+using testing::Test;
+
+namespace
+{
+  class JniReturnValueTest : public Test
+  {
+    public:
+
+      JniReturnValueTest() = default;
+      ~JniReturnValueTest() override = default;
+  };
+
+  TEST_F(JniReturnValueTest, getByteValue)
+  {
+    JniReturnValue returnValue{};
+    ASSERT_EQ(0, returnValue.getByteValue());
+  }
+
+  TEST_F(JniReturnValueTest, setByteValue)
+  {
+    JniReturnValue returnValue{};
+    returnValue.setByteValue(22);
+
+    ASSERT_EQ(22, returnValue.getByteValue());
+  }
+}

+ 2 - 1
test/classes/core/jni/MockJniApi.hpp

@@ -3,7 +3,7 @@
 * Company:         Lynar Studios
 * E-Mail:          webmaster@lynarstudios.com
 * Created:         2023-04-07
-* Changed:         2023-04-07
+* Changed:         2023-04-08
 *
 * */
 
@@ -22,6 +22,7 @@ namespace test::core::jni
       MockJniApi();
       ~MockJniApi() noexcept override;
 
+      MOCK_METHOD(jbyte, callByteMethod, (jobject _javaObject, jmethodID _methodId), (override));
       MOCK_METHOD(jclass, findClass, (const ::std::string &_classPath), (override));
       MOCK_METHOD(jmethodID, getMethodId, (jclass _javaClass, const char *_methodIdentifier, const char *_methodSignature), (override));
   };