whenNew in Kotlin unit test & Missing calls inside every block - unit-testing

Specifically asking, is there a Kotlin version for this java statement?
whenNew(myClass.class).withAnyArguments().thenReturn(myObject);
I have looked everywhere and haven't found anything that has worked for me yet.
I have tried:
every { myClass(any(), any()) } returns myObject
To this I get this error - argumentA must be in the form m.n. This tells me that blank arguments are being fed to myClass constructor but this is not my motive. I want this class to always return myObject whenever a constructor is being called, irrespective of the arguments.
I have also tried this:
every { myClass(TEST_A, TEST_B) } returns myObject
Then I get this error - Missing calls inside every { ... } block.
Another key point to add is - this is not the class I am writing the test for. I am writing the test cases for myOtherClass (actually defined in kotlin as an object, see below). Within one of the methods in myOtherClass, myClass is instantiated by feeding a set of arguments to its public constructor.
object myOtherClass {
fun mainFunction(a: A, b: B): X {
val answer = getAnswer(a, b)
y = convertAnswerToX(answer)
return y
}
private fun getAnswer(a: A, b: B): myClass {
val a1 = doSomethingToA(a)
val b1 = doSomethingToB(b)
return myClass(a1, b1)
}
}

Related

Mock call not being detected

I created a test case with Catch2 and I am trying to use TrompeLoeil for finer testing.
However the mock calls either don't happen at all, or happen but don't seem to be detecting by the framework.
Here is a minimal reproductible example :
class MyRealClass
{
public:
virtual int returnSumOfValues(int a, int b)
{
return a + b;
}
};
class MyMockClass : public MyRealClass
{
public:
MAKE_MOCK2(returnSumOfValues, int(int,int));
};
class MyTestedClass
{
public:
MyTestedClass(MyRealClass* _computeObj)
: computeObj(_computeObj)
{
}
int compute()
{
return computeObj->returnSumOfValues(2,3);
}
MyRealClass* computeObj;
};
TEST_CASE("Testing Trompe L'oeil")
{
auto mock = new MyMockClass();
MyTestedClass testedClass(mock);
int val = testedClass.compute();
CHECK(val == 5);
REQUIRE_CALL(*mock, returnSumOfValues(2,3)).RETURN(5);
}
And here is the error I get from running this test :
------------------------------------------------------------------------------- Testing Trompe L'oeil
------------------------------------------------------------------------------- ../../../src/MEGAAutoTests/UnitTests/control/TransferBatchTests.cpp:164
...............................................................................
../../../src/MEGAAutoTests/UnitTests/main.cpp:38: FAILED: explicitly
with message: No match for call of returnSumOfValues with signature
int(int,int) with.
param _1 == 2
param _2 == 3
I debugged this step by step and the mocked returnSumOfValues() is the one being executed.
However, if I make MyRealClass::returnSumOfValues() not virtual, the mock class is not used at all.
And the error is :
------------------------------------------------------------------------------- Testing Trompe L'oeil
------------------------------------------------------------------------------- ../../../src/MEGAAutoTests/UnitTests/control/TransferBatchTests.cpp:164
...............................................................................
../../../src/MEGAAutoTests/UnitTests/main.cpp:43: FAILED: CHECK(
failure.empty() ) with expansion: false with message: failure :=
"../../../src/MEGAAutoTests/UnitTests/control/TransferBatchTests.
cpp:172 Unfulfilled expectation: Expected
*mock.returnSumOfValues(2,3) to be called once, actually never called
param _1 == 2
param _2 == 3 "
This seems to not be consistent with the official documentation, which states that :
The line MAKE_MOCK2(log, void(int severity, const std::string& msg))
creates a mock function void Logger::log(int, const std::string&). If
MAKE_MOCKn(...) or MAKE_CONST_MOCKn(...) are used to implement a
virtual function from a base class, it is always recommended to add a
third macro parameter override since it gives the compiler an ability
to complain about mistakes.
Recommended, not required. And to give the compiler more information, not to make the test work.
TL, DR
Why is my code sample not working?
Why do I need to make mocked functions virtual when the documentation suggests it is not mandatory?
The issue was that expectations need to be set beforehand.
I though they worked like assertions, checking a state after the code was executed, but this is not the case.
In this case, moving the call solved the problem. Here is the fixed code sample :
TEST_CASE("Testing Trompe L'oeil")
{
auto mock = new MyMockClass();
MyTestedClass testedClass(mock);
REQUIRE_CALL(*mock, returnSumOfValues(2,3)).RETURN(5);
int val = testedClass.compute();
CHECK(val == 5);
}
This is the solution to the first problem, the second one (only virtual functions can be mocked) remains unanswered.

Using spy to mock a full object created in the class which is tested

I have the following structure:
class A {
public A(String p){
// ...
}
public String AMethod(String p){
// ...
}
}
class B {
int method(String param){
A a = new A(param); int n;
String s = A.AMethod(param);
// ... (initializes n, ...)
return n;
}
}
Now I want to test method in class B but control the output of AMethod when it is called. But since I do not create the object A in the test class of B, I cannot mock it normally - how can I mock object A instead?
I tried Mockito.spy but it doesn't seem to work:
this.ASpy = spy(new A());
when(ASpy.createSession(any())).then(invocation -> {
// ... (*)
});
(*) still doen't get called... but spy should be the right solution, shouldn't it? My problem is: I never create an object A in my test class, only in method such an object is created but not in the test class.
The best way to handle this (if possible) would be to modify the code of class B so that object A was injected into the method (passed as a parameter, set as a class field or instantiated with usage of a factory class - the factory would be injected as a field and the factory object could be mocked in the test to return a mocked object A).
If actual code modifications are not possible, you could use PowerMock's whenNew method and return a mocked object in your test.
A side note: if you're using JUnit 5, PowerMock may not be a viable solution - read more here.

How do I verify calls being made to a parameter used as delegate (delegation)?

I have a class A like the following:
class A(b: B) : B by b // Note the implementation of interface B by delegation to parameter b
interface B {
fun memberFunction() {}
}
fun B.extensionFunction() {}
I now want to verify that B#extensionFunction is being called. How do I do that?
I can verify B#memberFunction like so:
class BImpl : B // Dummy implementation needed to instantiate interface B
#Test
fun `memberFunction can be verified`() {
val bSpy = spyk<B>(BImpl)
val a = A(bSpy)
a.memberFunction()
verify { bSpy.memberFunction() }
}
However, the same test for B#extensionFunction doesn't do the trick; instead, I get a java.lang.AssertionError. The verification fails, because the call didn't happen. (Note that you have to use a static mock (using the mockkStatic function) to be able to verify an extension function.)
For reference, libraries used:
org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.11
junit:junit:4.12
io.mockk:mockk:1.9
You can trivially verify extension function being called on the delegator itself, i.e. in your example a:
#Test
fun `extensionFunction can be verified`() = mockkStatic("your.package.name.FilenameKt") {
val a = A(BImpl)
a.extensionFunction()
verify { a.extensionFunction() }
}
This looks trivial, but if the call to a.extensionFunction() is made downstream from another call in your test method, this verifies the extension method is being called on a.
This works simply because a is a B (through parameter b). Given that fact, you can verify the call being made on a.

should we create object of any class on class level or function level

Which approach is better: I tried to find it on web, but I couldn't get a better answer.
1.
public class OtherClass
{
public int Add(int x, int y)
{
return x + y;
}
}
public class TestClass
{
OtherClass oClass = new OtherClass();
public int Fun1()
{
return oClass.Add(1,2);
}
public int Fun2()
{
return oClass.Add(1, 2);
}
}
2.
public class TestClass
{
public int Fun1()
{
OtherClass oClass = new OtherClass();
return oClass.Add(1, 2);
}
public int Fun2()
{
OtherClass oClass = new OtherClass();
return oClass.Add(1, 2);
}
}
I think it depends on what you are trying to test.
If you're testing the effects of a sequence of functions being executed on the same class instance then you might want to create a single instance (such as stress testing)
But otherwise I'd say it's always better to create a new instance of the class in each test function to ensure that the context of each test is predictable. If your test methods shared an instance of a class, and one test method fails and corrupts the state of the object under test, your subsequent test may fail for no other reason than the state of the object under test was corrupted by the previous failed test (it might appear the multiple tests are failing when in fact only one of the early ones is a true failure).
Depends on the scenario, if the class is gonna be shared on multiple functions and there are no specific arguments needed to create an instance of that class then it's better of being at the class level.
Let's say you're using the Fun1 and Fun2 often, having the instance creation on the method will have instance creation overhead rather than it being at the class level having a single instance, or better yet, make it static or make it singleton if you're sure that it's going to be a single instance throughout the whole app.
One benefit of having it in the class level is if you're doing unit testing, you can make an interface like IOtherClass and Inject it in the constructor of TestClass.
It would look something like this.
public class OtherClass : IOtherClass
{
public int Add(int x, int y)
{
return x + y;
}
}
public class TestClass
{
IOtherClass oClass;
public TestClass(IOtherClass _oClass)
{
oClass = _oClass;
}
public int Fun1()
{
return oClass.Add(1,2);
}
public int Fun2()
{
return oClass.Add(1, 2);
}
}
You're better off having it as a field in the class rather than declaring a new one in each method. The reason for this is simple, there won't be a line of code in each method declaring the variable meaning that if your declaration statement changes you will only have to change it in one place, not every method. Also it will make your code easier to read and add to because this line won't be duplicated everywhere.
Just remember if that field needs to be disposed your class should implement the IDisposable interface.

How do I unit-test a class that depends on another class to change the state of something?

I have a class A which contains an instance of class B, and function foo of A calls function set of B, which updates the state of B. Here is a code example (in Javascript):
A = function () {
this.init = function (b) {
this.b = b
}
this.foo = function (val) {
this.b.set(val)
}
this.bar = function () {
return this.b.get()
}
}
B = function () {
this.set = function (val) {
this.v = val
}
this.get = function () {
return this.v
}
}
How do I unit-test the foo function, while keeping the test for A non-dependent on the implementation of B (using mocks and stubs and what not)?
Using mocks, you can simply hand A a mock of B, which will check that set was called with the appropriate value. If you don't have a mock framework, in JavaScript you can simply create an object:
b = {
setCalled: false,
expectedValue: <expected>
set: function(val) {
<check that val == this.expectedValue>
this.setCalled = true;
}
}
in the test you setup b, create an A with the given b then call A.foo and check that b.setCalled changed to true. You can similarly add a get method to b to check A.bar.
In this case you also should check the smell Feature Envy -- when two classes are this tightly coupled you should check to make certain you are not using something incorrectly. It may be fine in your real example, but it is worth a check.
I figured out the best way to do this, while making sure that A's test doesn't depend on its implementation, would be to create a mock B that has a working get and set, but writes to a temporary variable.
Code example to test A:
// Mock B
b = new function () {
this.set = function (val) {
this.v = val
}
this.get = function () {
return this.v
}
}
// Create an instance of A with Mock B
a = new A().init(b)
// Test A
// ...