Test a call in Kotlin object - unit-testing

I have a Kotlin class like this one
import org.slf4j.LoggerFactory.getLogger
object Doer {
val logger = LoggerFactory.getLogger(Doer::class.java)
fun doSomething() : Int {
logger.warn("Doing.")
return 123
}
}
I would like to have a unit test that verifies logger.warn call was made with relevant message. How do I do this in Kotlin?
One of my ideas was to use a getter for logger and stub that with Mockito, but do I need to declare such method explicitly given that Kotlin generates getters automatically? Method getLogger() is not visible in Doer class, but if I declare it explicitly it conflicts with generated one.
Are there better options to test this?
Second question is how to mock the object instance, since it is initialized by language which is out of my control?

Related

Mock a "global" property in Kotlin

Is there a way to change the return value of the property accessor called when running unit tests? Like mocking the result of the property settingsState?
I am learning to create unit tests. What that class makes is to bring stored data into the program, this data is given in a visual form. In my test, I want to define what is going on there because the window won't open there.
// top-level declaration outside class
val settingsState: ApplicationSettingsState
get() = ServiceManager.getService(ApplicationSettingsState::class.java)
settingsState is not a variable. It is a property.
I am not aware of any way to mock global properties (or global functions). The way mocking works is to cleverly create an object that looks a bit like the object to mock from the outside, but behaves differently on the inside. In the absence of an object to mock, there is no way to mock.
That said, on the bytecode level there are no global variables, properties, whatever. They are all wrapped into classes, because the JVM likes it that way. Some clever bytecode manipulation might be able to achieve some effect – but not MockK.
You can mock the property if you have a mocked object. To paraphrase the documentation:
val mock = mockk(Bus())
every { mock getProperty "speed" } returns 33
Yes you can. You want to mock a property that is declared at top-level. Top-level code in a given Kotlin file MyFile.kt is actually compiled to be inside the class MyFileKt. Let's say we have following Kotlin file named MyFile.kt:
package foo
val bar = "some value"
If we compile this file to JVM bytecode and then decompile the result to Java, we get a Java class that looks similar to this:
package foo;
public final class MyFileKt {
private static final String bar = "some value";
public static final String getBar() {
return bar;
}
}
As you can see, our top-level val we defined earlier is actually translated to a static field with associated getter in the class MyFileKt.
TLDR; Getting back to our original problem, all you need to do is statically mock this field:
mockkStatic("foo.MyFileKt") // Fully-qualified name of the generated class
every { bar } returns "some other test value" // Define what our top-level property should return
The same also works for top-level functions, of course.

What should be the strategy for Unit testing a method calling other methods in the same class?

I am writing unit tests for a class that has a method that calls other methods of the same class. This is leading to a lot of scenarios to be tested.
I am of the opinion that I can spy() the behaviour of the method calls so that I am testing only the method under test and not bothered about other methods behaviour. I will cover them through a separate test for each of those methods.
class MyClass{
public void myMethodToBeTested(){
aPrivateMethod();
aPublicMethod();
}
private void aPrivateMethod(){
// doing something
// Has some if else scenarios
}
public void aPublicMethod(){
// doing something
// Has some if else scenarios
}
}
What would be best way to unit test this class?
You should test by calling the external interface of the class i.e. the public methods.
If those methods call private methods in the same class, then those private methods need to be fully covered too - otherwise how would they be tested?
Stubbing or spying only makes sense for calls to resources or classes outside the class under test.
You're trying to test the entire class, not just individual methods.
In my view the aPrivateMethod could go to a separate class as public and also the body of the aPublicMethod could be a different method in that class.
After this refactoring you can inject the new class and call those methods in the corresponding places.
When it comes to testing, you could mock/stub those methods and test the myMethodToBeTested().
First off, I'd change the private method to default / package-level. That way, a unit test occupying the same package can access it but other methods, outside of that package, can't touch it. Not quite the same thing as private scope, but close enough most of the time.
Then, setup a Spy() on MyClass.
In case you're not clear on that term:
A Mock() on a class will always return null or 0 to any method call
A Stub() on a class lets you define what certain methods in that class should do, but anything you DON'T explicitly specify always returns a null or 0
A Spy() lets you create an object of a class, with all methods in place EXCEPT you can override some of those methods
So create a Spy(MyClass), specify what aPrivateMethod() and aPublicMethod() should return for testing purposes then call myMethodToBeTested() and see what is returned. In your example, that method is void, so it doesn't return anything. But you can always:
define a variable outside of the Spy()
have aPublicMethod() set / modify the variable based on inputs or internal state (your overriding methods in your Spy() can take parameters)
call myMethodToBeTested()
check the contents of that variable

Rhino Mock Expect.Call() actually calls the method not only create an expectation

I want to test if a method has been called in the test.
My problem is that when I want to create the expectations it is not working as I thought. The next line actually runs the method, not only create an expectation:
Expect.Call(() => mockedService.MethodThatIExpectToRun(params));
There is another way:
mockedService.Expect((s=> s.MethodThatIExpectToRun(params)));
But this also actually runs the method, not only creates an expectation to be fulfilled by the test.
And this line that asserts if the method was not called also actually calls the method, not only checks whether it was called.
mockedService.AssertWasCalled(s=> s.MethodThatIExpectToRun((params)));
additional info:
MethodThatIExpectToRun returns void
For prgmtc's comment:
IService mockedService = MockRepository.GeneratePartialMock<Service>(mockedRepository_1, ..., mockedRepository_n);
Usually when you have PartialMock that's calling the real method when setting a Stub or Expect, it means the virtual keyword is missing on the method.
Make sure Service.MethodThatIExpectToRun is virtual.
A more general (although perhaps less useful) remark: Partial mocks can point to a design smell of the code under test. If you only want to provide expectations for a part of a class, then perhaps that class has too many responsibilities and should be split into multiple classes? That way you can cleanly isolate responsibilities/collaborators and have no need for the partialmock construct. If you mock (not partial mock) an interface or virtual member of a concrete class the call won't go through to the real implementation.
For example:
Console.WriteLine("Real object: ");
new Foo().Bar();
Console.WriteLine("Mocked object: ");
var aFoo = MockRepository.GenerateMock<Foo>();
aFoo.Expect(f => f.Bar());
aFoo.Bar();
...
public class Foo
{
public virtual void Bar()
{
Console.WriteLine("REAL IMPLEMENTATION");
}
}
Outputs:
Real object:
REAL IMPLEMENTATION
Mocked object:

How to test a method that calls another class' method?

I'm fairly new to unit testing. I've recently encountered a problem where I test a method that does one thing only - it calls a method of an object that's part of the class. The class that this object represents has it's own unit tests.
I understand that this method may change in time, and when it does the test should inform me about if the expected result it. But what can I test in such a method?
My code:
public class MyClassToBeTested
{
private CustomType myObject;
private const myParameter = 2;
(...)
public string MyProperty
{
get
{
return myObject.DoYourStuff(myParameter);
}
}
}
This sounds like you need to capture the call to the underlying object and inspect it (or at least verify that the call has been made). I would mock this object and inject a reference to it (Inversion of Control).
By injecting the object you can provide the real object at deploy time, and the mock during testing.
If something is dependent on something else. i.e. method calls another method, then you should mock it, or simulate its behaviour.

How do I mock static property Groovy?

I saw a lot of examples how to mock a static method in a class.
I want to mock a static property of the class, that's initialized in its definition.
Something like:
class MyClass {
private static log = LogFactory.getLog(this)
}
I want to mock log property, in order that in my test it should be null, and it should not initialize itself.
Make static getter method :
static def getLog() {
return log
}
Use metaClass.staticto mock method:
Myclass.metaClass.static.getLog = {
return "what you need"
}
You are referring to 'log' as a property, but it's actually not. Assuming that MyClass is a Groovy class, then a property is declared without a private or public modifier, like this:
class MyClass {
static log = LogFactory.getLog(this)
}
What you have is a private static variable with an initializer. In this case, no property access methods are generated, and the variable is not considered a property.
Because it's a private variable with an initializer, and you state that you don't want to change the class, you cannot stop the initializer from running. So the best thing to do here is to mock out the getLog() call to return null. A simple but crude approach would be:
LogFactory.metaClass.static.getLog = {
return null
}
but this will kill all log lookup in the whole application. This could be OK for a simple unit test, but a more specific solution is to use Groovy mocks (MockFor and StubFor), which will allow you to mock the getLog call in a specific block of code. You can find out more here
As a matter of interest, why do you not want the log variable initialized?